6b294b772c422b6da570112432e52ff3c3e71de0
[platform/core/connectivity/wifi-direct-manager.git] / src / wifi-direct-session.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 session functions.
22  *
23  * @file                wifi-direct-session.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 <string.h>
31
32 #include <glib.h>
33
34 #include <wifi-direct.h>
35
36 #include "wifi-direct-ipc.h"
37 #include "wifi-direct-manager.h"
38 #include "wifi-direct-oem.h"
39 #include "wifi-direct-peer.h"
40 #include "wifi-direct-group.h"
41 #include "wifi-direct-oem.h"
42 #include "wifi-direct-util.h"
43 #include "wifi-direct-session.h"
44 #include "wifi-direct-state.h"
45 #include "wifi-direct-error.h"
46 #include "wifi-direct-log.h"
47 #include "wifi-direct-dbus.h"
48 #include "wifi-direct-asp.h"
49
50 //LCOV_EXCL_START
51 static gboolean _session_timeout_cb(gpointer *user_data)
52 {
53         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
54         wfd_manager_s *manager = wfd_get_manager();
55         wfd_session_s *session = (wfd_session_s*) manager->session;
56         unsigned char *peer_addr = NULL;
57         char peer_mac_address[MACSTR_LEN+1] = {0, };
58
59         if (!session) {
60                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
61                 return FALSE;
62         }
63         session->connecting_120 = 0;
64         session->timer = 0;
65         WDS_LOGD("Session timer expired");//LCOV_EXCL_LINE
66
67         peer_addr = wfd_session_get_peer_addr(session);
68         if (peer_addr != NULL)
69                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
70         else
71                 g_snprintf(peer_mac_address, MACSTR_LEN, "%s", "");
72
73         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
74                                      "Connection",
75                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT,
76                                                             WFD_EVENT_CONNECTION_RSP,
77                                                             peer_mac_address));
78
79         if (wfd_asp_is_asp_session(session)) {
80                 if (session->state < SESSION_STATE_GO_NEG)
81                         wfd_asp_connect_status(session->session_mac,
82                                         session->session_id,
83                                         ASP_CONNECT_STATUS_REQUEST_FAILED,
84                                         NULL);
85                 else
86                         wfd_asp_connect_status(session->session_mac,
87                                         session->session_id,
88                                         ASP_CONNECT_STATUS_GROUP_FORMATION_FAILED,
89                                         NULL);
90         }
91
92         wfd_session_cancel(session, peer_addr);
93
94         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
95
96                 wfd_group_s *group = (wfd_group_s*) manager->group;
97                 if (group && wfd_util_is_remove_group_allowed()) {
98                         wfd_oem_destroy_group(manager->oem_ops, group->ifname);
99                 } else {
100                         wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
101                         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
102                 }
103         } else {
104                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
105                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
106         }
107
108         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
109         return FALSE;
110 }
111 //LCOV_EXCL_STOP
112
113 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
114 {
115         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
116         char peer_mac_address[MACSTR_LEN+1] = {0, };
117
118         snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
119         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
120                                      "Connection",
121                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_FAILED,
122                                                             WFD_EVENT_CONNECTION_RSP,
123                                                             peer_mac_address));
124
125
126
127         wfd_session_s *session = manager->session;
128         if (wfd_asp_is_asp_session(session)) {
129                 wfd_asp_connect_status(session->session_mac,
130                                                         session->session_id,
131                                                         ASP_CONNECT_STATUS_GROUP_FORMATION_STARTED,
132                                                         NULL);
133         }
134
135         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
136                 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
137                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
138         } else {
139                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
140                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
141         }
142
143         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
144 }
145
146 int wfd_session_timer(wfd_session_s *session, int start)
147 {
148         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
149
150         if (!session) {
151                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
152                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
153                 return -1;
154         }
155
156         if (start) {
157                 if (!session->connecting_120)
158                         session->connecting_120 = 1;
159
160                 if (session->timer > 0) {
161                         WDS_LOGE("Session timer already started");//LCOV_EXCL_LINE
162                         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
163                         return -1;
164                 }
165                 session->timer = g_timeout_add(120000,
166                                                 (GSourceFunc) _session_timeout_cb,
167                                                 NULL);
168                 WDS_LOGD("Session timer started");//LCOV_EXCL_LINE
169         } else {
170                 session->connecting_120 = 0;
171                 if (session->timer > 0) {
172                         g_source_remove(session->timer);
173                         session->timer = 0;
174                         WDS_LOGD("Session timer stoped");//LCOV_EXCL_LINE
175                 }
176         }
177
178         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
179         return 0;
180 }
181
182 /* Check the session instance which has same peer address,
183  * before using this function */
184 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
185 {
186         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
187         wfd_manager_s *manager = (wfd_manager_s*) data;
188         wfd_session_s *session = NULL;
189         wfd_device_s *peer = NULL;
190
191         if (!data || !peer_addr) {
192                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
193                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
194                 return NULL;
195         }
196
197         WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
198
199         if (manager->session) {
200                 WDS_LOGE("Session already exist");//LCOV_EXCL_LINE
201                 return NULL;
202         }
203
204         session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
205         if (!session) {
206                 WDS_LOGE("Failed to allocate memory for session");//LCOV_EXCL_LINE
207                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
208                 return NULL;
209         }
210
211         peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
212         if (!peer) {
213                 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
214                 g_free(session);
215                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
216                 return NULL;
217         }
218         peer->state = WFD_PEER_STATE_CONNECTING;
219
220         session->peer = peer;
221         session->req_wps_mode = wps_mode;
222         if (wps_mode == WFD_WPS_MODE_DISPLAY)
223                 session->wps_mode = WFD_WPS_MODE_KEYPAD;
224         else if (wps_mode == WFD_WPS_MODE_KEYPAD)
225                 session->wps_mode = WFD_WPS_MODE_DISPLAY;
226         else if (wps_mode == WFD_WPS_MODE_P2PS)
227                 session->wps_mode = WFD_WPS_MODE_P2PS;
228         else
229                 session->wps_mode = wps_mode;
230         session->direction = direction;
231         session->state = SESSION_STATE_CREATED;
232
233         manager->session = session;
234         manager->local->wps_mode = session->wps_mode;
235
236         if (peer->dev_role == WFD_DEV_ROLE_GO &&
237                         manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
238                         char *generated_pin = NULL;
239                         session->wps_mode = WFD_WPS_MODE_DISPLAY;
240                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
241
242                         if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
243                                 WDS_LOGE("Failed to generate pin");//LCOV_EXCL_LINE
244                                 g_free(session);
245                                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
246                                 return NULL;
247                         }
248
249 #if defined(BUILD_GTESTS)
250                         generated_pin = g_strndup("12345678", PINSTR_LEN + 1);
251 #endif /* BUILD_GTESTS */
252                         g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
253                         g_free(generated_pin);
254         }
255
256         if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
257                 manager->local->dev_role = WFD_DEV_ROLE_GC;
258
259         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
260         return session;
261 }
262
263 int wfd_destroy_session(void *data)
264 {
265         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
266         wfd_manager_s *manager = (wfd_manager_s*) data;
267         wfd_session_s *session = NULL;
268         wfd_device_s *peer = NULL;
269
270         if (!manager) {
271                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
272                 return -1;
273         }
274
275         session = (wfd_session_s*) manager->session;
276         if (!session) {
277                 WDS_LOGE("Session not found");//LCOV_EXCL_LINE  /* self prevent */
278                 return -1;
279         }
280         wfd_session_timer(session, 0);
281         peer = session->peer;
282         WDS_LOGD("peer :%p", peer);
283
284         if (peer) {
285                 if (session->state == SESSION_STATE_COMPLETED)
286                         peer->state = WFD_PEER_STATE_CONNECTED;
287                 else
288                         peer->state = WFD_PEER_STATE_DISCOVERED;
289         } else {
290                 WDS_LOGE("Peer not found");//LCOV_EXCL_LINE
291         }
292
293         g_free(session);
294         manager->session = NULL;
295         manager->local->wps_mode = WFD_WPS_MODE_PBC;
296         manager->autoconnection = 0;
297         memset(manager->auto_pin, 0x0, PINSTR_LEN);
298         if (manager->local->dev_role == WFD_DEV_ROLE_GC)
299                 manager->local->dev_role = WFD_DEV_ROLE_NONE;
300
301         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
302         return 0;
303 }
304
305 int wfd_session_start(wfd_session_s *session)
306 {
307         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
308         wfd_manager_s *manager = wfd_get_manager();
309         wfd_device_s *peer = NULL;
310         int join = 0;
311         int res = 0;
312
313         if (!session) {
314                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
315                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
316                 return -1;
317         }
318
319         if (session->state > SESSION_STATE_STARTED) {
320                 WDS_LOGE("Invalid session state(%d)", session->state);
321                 return -1;
322         }
323
324         /* Check: Invitation Received in Incomming case ->
325          * send prov_disc join
326          *
327          * Check: User select peer to connect with in Outgoing case ->
328          * send prov_disc wps_mode */
329
330         wfd_oem_stop_scan(manager->oem_ops);
331
332         session->state = SESSION_STATE_STARTED;
333         peer = session->peer;
334         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
335                 join = 1;
336         res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
337                                         session->req_wps_mode, join);
338         if (res < 0) {
339                 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
340                                                                         MAC2SECSTR(peer->dev_addr));
341                 wfd_destroy_session(manager);
342                 /* TODO: send notification to App */
343                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
344                 return -1;
345         }
346
347         wfd_session_timer(session, 1);
348
349         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
350         return 0;
351 }
352
353 int wfd_session_asp_session_start(wfd_session_s *session, wfd_oem_asp_prov_s *params)
354 {
355         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
356
357         wfd_manager_s *manager = wfd_get_manager();
358         int res = 0;
359
360         if (session == NULL || params == NULL) {
361                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
362                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
363                 return -1;
364         }
365
366         if (session->state > SESSION_STATE_STARTED) {
367                 WDS_LOGE("Invalid session state(%d)", session->state);
368                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
369                 return -1;
370         }
371
372         res = wfd_oem_asp_prov_disc_req(manager->oem_ops, params);
373         if (res < 0) {
374                 WDS_LOGD("Failed to send ASP provision discovery request to peer");//LCOV_EXCL_LINE
375                 wfd_destroy_session(manager);
376                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
377                 return -1;
378         }
379
380         session->state = SESSION_STATE_STARTED;
381         session->session_id = params->session_id;
382         memcpy(session->session_mac, params->session_mac, MACADDR_LEN);
383         memcpy(session->service_mac, params->service_mac, MACADDR_LEN);
384         wfd_session_timer(session, 1);
385
386         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
387         return 0;
388 }
389
390 #if 0
391 int wfd_session_stop(wfd_session_s *session)
392 {
393         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
394         wfd_manager_s *manager = wfd_get_manager();
395         wfd_device_s *peer = NULL;
396         int res = 0;
397
398         if (!session) {
399                 WDS_LOGE("Invalid parameter");
400                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
401                 return -1;
402         }
403
404         if (session->state > SESSION_STATE_CREATED) {
405                 peer = session->peer;
406                 if (session->direction == SESSION_DIRECTION_INCOMING)
407                         res  = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
408                 else if (session->direction == SESSION_DIRECTION_OUTGOING)
409                         res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
410
411                         if (res < 0) {
412                         WDS_LOGE("Failed to reject or cancel connection");
413                         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
414                         return -1;
415                 }
416         }
417
418         session->state = SESSION_STATE_STOPPED;
419         wfd_destroy_session(manager);
420
421         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
422         return 0;
423 }
424 #endif
425
426 /* In case of incomming session, when user accept connection request, this function should be called.
427  * In case of outgoing session, when prov_disc response arrived, this function should be called.
428  * Even though peer is GO, we can use this function, which can decide using join itself.
429  */
430 int wfd_session_connect(wfd_session_s *session)
431 {
432         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
433         wfd_manager_s *manager = wfd_get_manager();
434         wfd_oem_conn_param_s param;
435         wfd_device_s *peer = NULL;
436         int res = 0;
437
438         if (!session) {
439                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
440                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
441                 return -1;
442         }
443
444         if (session->state > SESSION_STATE_GO_NEG) {
445                 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
446                 return -1;
447         }
448
449         session->state = SESSION_STATE_GO_NEG;
450         peer = session->peer;
451
452         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
453         param.wps_mode = session->wps_mode;
454         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
455                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
456         param.go_intent = session->go_intent;
457         if (peer->display.availability)
458                 param.go_intent = manager->go_intent_per_type[manager->local->display.type];
459         param.freq = session->freq;
460         if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
461                 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
462
463         if (session->wps_pin[0] != '\0')
464                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
465
466         /* To connect with windows phone,set go_intent value to 2.
467         *  As windows phone does not connect when local device act as GO.
468         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
469         *  WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
470         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
471         */
472          if ((peer->pri_dev_type == 1) ||
473                                  ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
474                 param.go_intent = 2;
475                 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
476          }
477
478         WDS_LOGD("connection go_intent: %d", param.go_intent);
479         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
480         if (res < 0) {
481                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
482                 wfd_destroy_session(manager);
483                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
484                 return -1;
485         }
486
487         wfd_session_timer(session, 1);
488
489         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
490         return 0;
491 }
492
493 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
494 {
495         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
496         wfd_manager_s *manager = wfd_get_manager();
497         int res = 0;
498
499         if (!session || !session->peer) {
500                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
501                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
502                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
503         }
504
505         if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
506                 WDS_LOGE("Peer is not included in this session");//LCOV_EXCL_LINE
507                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
508         }
509
510         if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
511                 res = wfd_oem_wps_cancel(manager->oem_ops);
512         else
513                 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
514
515         if (res < 0) {
516                 WDS_LOGE("Failed to cancel connection");//LCOV_EXCL_LINE
517                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
518         }
519
520         wfd_destroy_session(manager);
521
522         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
523         return 0;
524 }
525
526 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
527 {
528         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
529         wfd_manager_s *manager = wfd_get_manager();
530         wfd_device_s *peer = NULL;
531         int res = 0;
532
533         if (!session || !manager) {
534                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
535                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
536                 return -1;
537         }
538
539         /* Invite received case state is just created */
540         if (session->state < SESSION_STATE_CREATED ||
541                 session->state >= SESSION_STATE_STOPPED) {
542                 WDS_LOGE("Session state is Invalid [%d]", session->state);
543                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
544                 return -1;
545         }
546
547         /*
548          * TODO: check session status and do proper work
549          * for example, reject prov_disc, reject nego, stop wps, etc.
550          *
551          */
552
553         peer = session->peer;
554
555         if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
556                 res = wfd_oem_wps_cancel(manager->oem_ops);
557         else
558                 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
559         if (res < 0) {
560                 WDS_LOGE("Failed to reject connection");//LCOV_EXCL_LINE
561                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
562                 return -1;
563         }
564
565         wfd_destroy_session(manager);
566         /* TODO: send notification to App */
567
568         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
569         return 0;
570 }
571
572 int wfd_session_join(wfd_session_s *session)
573 {
574         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
575         wfd_manager_s *manager = wfd_get_manager();
576         wfd_oem_conn_param_s param;
577         wfd_device_s *peer = NULL;
578         int res = 0;
579
580         if (!session) {
581                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
582                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
583                 return -1;
584         }
585
586         session->state = SESSION_STATE_WPS;
587         peer = session->peer;
588
589         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
590         param.wps_mode = session->wps_mode;
591         if (peer->dev_role == WFD_DEV_ROLE_GO)
592                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
593         param.go_intent = session->go_intent;
594         param.freq = session->freq;
595         g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
596
597         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
598         if (res < 0) {
599                 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
600                 wfd_destroy_session(manager);
601                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
602                 return -1;
603         }
604
605         wfd_session_timer(session, 1);
606
607         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
608         return 0;
609 }
610
611 int wfd_session_invite(wfd_session_s *session)
612 {
613         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
614         wfd_manager_s *manager = wfd_get_manager();
615         wfd_oem_invite_param_s param;
616         wfd_device_s *peer = NULL;
617         wfd_group_s *group = NULL;
618         int res = 0;
619
620         if (!session) {
621                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
622                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
623                 return -1;
624         }
625
626         if (session->state > SESSION_STATE_CREATED) {
627                 WDS_LOGE("Invalid session state(%d)", session->state);
628                 return -1;
629         }
630
631         peer = session->peer;
632         group = (wfd_group_s*) manager->group;
633
634         memset(&param, 0x00, sizeof(wfd_oem_invite_param_s));
635         param.ifname = g_strdup(group->ifname);
636         memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
637
638         WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
639                                 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
640
641         res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, &param);
642         if (res < 0) {
643                 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
644                 wfd_destroy_session(manager);
645                 g_free(param.ifname);
646                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
647                 return -1;
648         }
649
650         wfd_session_timer(session, 1);
651         g_free(param.ifname);
652
653         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
654         return 0;
655 }
656
657 int wfd_session_wps(wfd_session_s *session)
658 {
659         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
660         wfd_manager_s *manager = wfd_get_manager();
661         wfd_device_s *peer = NULL;
662         int res = 0;
663
664         if (!session) {
665                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
666                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
667                 return -1;
668         }
669
670         if (session->state > SESSION_STATE_WPS) {
671                 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
672                 return -1;
673         }
674
675         session->state = SESSION_STATE_WPS;
676         peer = session->peer;
677
678         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
679                 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
680                 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
681         } else {
682                 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
683                 wfd_oem_conn_param_s param;
684                 memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
685                 param.wps_mode = session->wps_mode;
686                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
687                 param.freq = session->freq;     /* currently not used */
688                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
689                 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
690         }
691         if (res < 0) {
692                 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
693                 wfd_destroy_session(manager);
694                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
695                 return -1;
696         }
697
698         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
699         return 0;
700 }
701
702 /* In case of incomming session, when user accept connection request, this function should be called.
703  * In case of outgoing session, when prov_disc response arrived, this function should be called.
704  * Even though peer is GO, we can use this function, which can decide using join itself.
705  */
706 int wfd_session_asp_connect(wfd_session_s *session, int role)
707 {
708         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
709         wfd_manager_s *manager = wfd_get_manager();
710         wfd_oem_conn_param_s param;
711         wfd_device_s *peer = NULL;
712         int res = 0;
713
714         if (!session) {
715                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
716                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
717                 return -1;
718         }
719
720         if (session->state >= SESSION_STATE_GO_NEG) {
721                 WDS_LOGE("Session already starting GO Negotiation");//LCOV_EXCL_LINE
722                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
723                 return -1;
724         }
725
726         if (role == WFD_OEM_ASP_SESSION_ROLE_GO) {
727                 session->state = SESSION_STATE_WPS;
728                 return 0;
729         } else {
730                 session->state = SESSION_STATE_GO_NEG;
731         }
732
733         peer = session->peer;
734
735         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
736         param.wps_mode = session->wps_mode;
737         if (role == 2)
738                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
739         param.go_intent = session->go_intent;
740         param.freq = session->freq;
741         param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
742
743         if (session->wps_pin[0] != '\0')
744                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
745
746         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
747         if (res < 0) {
748                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
749                 wfd_destroy_session(manager);
750                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
751                 return -1;
752         }
753
754         wfd_session_timer(session, 1);
755
756         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
757         return 0;
758 }
759
760 /* In case of incomming session, when user accept connection request, this function should be called.
761  * In case of outgoing session, when prov_disc response arrived, this function should be called.
762  * Even though peer is GO, we can use this function, which can decide using join itself.
763  */
764 int wfd_session_asp_persistent_connect(wfd_session_s *session, int persist_group_id)
765 {
766         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
767         wfd_manager_s *manager = wfd_get_manager();
768         wfd_oem_group_param_s param;
769         int res = 0;
770
771         if (!session) {
772                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
773                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
774                 return -1;
775         }
776
777         if (session->state > SESSION_STATE_GO_NEG) {
778                 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
779                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
780                 return -1;
781         }
782
783         session->state = SESSION_STATE_WPS;
784
785         memset(&param, 0x0, sizeof(param));
786         param.persistent = 2;
787         param.persistent_group_id = persist_group_id;
788
789         res = wfd_oem_create_group(manager->oem_ops, &param);
790         if (res < 0) {
791                 WDS_LOGD("Failed to create persistent group for ASP");//LCOV_EXCL_LINE
792                 wfd_destroy_session(manager);
793                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
794                 return -1;
795         }
796
797         wfd_session_timer(session, 1);
798
799         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
800         return 0;
801 }
802
803 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
804 {
805         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
806         wfd_device_s *peer = NULL;
807
808         if (!session) {
809                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
810                 return NULL;
811         }
812
813         peer = session->peer;
814
815         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
816         return peer;
817 }
818
819 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
820 {
821         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
822         wfd_device_s *peer = NULL;
823
824         if (!session || !session->peer) {
825                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
826                 return NULL;
827         }
828
829         peer = session->peer;
830
831         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
832         return peer->dev_addr;
833 }
834
835 #if 0
836 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
837 {
838         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
839
840         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
841         return 0;
842 }
843
844 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
845 {
846         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
847
848         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
849         return 0;
850 }
851
852 int wfd_session_set_freq(wfd_session_s *session, int freq)
853 {
854         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
855
856         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
857         return 0;
858 }
859
860 int wfd_session_get_state(wfd_session_s *session)
861 {
862         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
863
864         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
865         return 0;
866 }
867
868 int wfd_session_set_state(wfd_session_s *session, int state)
869 {
870         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
871
872         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
873         return 0;
874 }
875 #endif
876
877 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
878 {
879         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
880         wfd_session_s *session = NULL;
881         int res = 0;
882
883         if (!manager || !event) {
884                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
885                 return -1;
886         }
887
888         WDS_LOGD("event ID [%d]", event->event_id);
889         session = manager->session;
890
891         switch (event->event_id) {
892         case WFD_OEM_EVENT_PROV_DISC_REQ:
893         {
894                 int req_wps_mode = WFD_WPS_MODE_NONE;
895
896                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
897                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
898                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
899                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
900                 else
901                         req_wps_mode = WFD_WPS_MODE_PBC;
902
903                 /* Only peer initiated connection or invitation session can be allowed */
904                 if (session) {
905                         if (session->type != SESSION_TYPE_INVITE) {
906                                 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
907                                                                 MAC2SECSTR(event->dev_addr));
908                                 break;
909                         }
910                         WDS_LOGD("=====> session already exist. (invitation session)");//LCOV_EXCL_LINE
911                         if (session->state > SESSION_STATE_WPS) {
912                                 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
913                                 break;
914                         }
915
916                         session->req_wps_mode = req_wps_mode;
917                         session->wps_mode = event->wps_mode;
918                 } else {
919                         session = wfd_create_session(manager, event->dev_addr,
920                                                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
921                         if (!session) {
922                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
923                                                                 MAC2SECSTR(event->dev_addr));
924                                 break;
925                         }
926                 }
927
928                 /* Update session */
929                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
930                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
931
932                 session->state = SESSION_STATE_STARTED;
933                 if (session->type == SESSION_TYPE_INVITE)
934                         WDS_LOGD("Invitation session");//LCOV_EXCL_LINE
935                 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
936                         session->type = SESSION_TYPE_JOIN;
937                 else
938                         session->type = SESSION_TYPE_NORMAL;
939
940                 wfd_session_timer(session, 1);
941
942                 /* Update local device */
943                 manager->local->wps_mode = event->wps_mode;
944
945                 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
946                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
947
948                 if (session->type == SESSION_TYPE_INVITE) {
949                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
950                         if (session->wps_mode != WFD_WPS_MODE_PBC) {
951                                 char peer_mac_address[MACSTR_LEN+1] = {0, };
952
953                                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
954                                 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
955                                                              "Connection",
956                                                              g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
957                                                                                     WFD_EVENT_CONNECTION_WPS_REQ,
958                                                                                     peer_mac_address));
959                                 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
960                                         /* We have to wait until user type PIN using Keypad */
961                                         break;
962                                 }
963                         }
964                         res = wfd_session_wps(session);
965                         if (res < 0)
966                                 _wfd_notify_session_failed(manager, event->dev_addr);
967                 } else {
968                         char peer_mac_address[MACSTR_LEN+1] = {0, };
969
970                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
971                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
972                                                      "Connection",
973                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
974                                                                             WFD_EVENT_CONNECTION_REQ,
975                                                                             peer_mac_address));
976                 }
977         }
978         break;
979         case WFD_OEM_EVENT_PROV_DISC_RESP:
980         {
981                 if (!session) {         /* TODO: check validity of Event */
982                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
983                                                                                 MAC2SECSTR(event->dev_addr));
984                         break;
985                 }
986
987                 if (session->state > SESSION_STATE_STARTED) {
988                         WDS_LOGE("Unexpected event. Session is already started");//LCOV_EXCL_LINE
989                         break;
990                 }
991
992                 if (session->type == SESSION_TYPE_INVITE) {
993                         WDS_LOGE("Session type is invite, ignore provision discovery response");//LCOV_EXCL_LINE
994                         break;
995                 }
996
997                 /* Update session */
998                 session->wps_mode = event->wps_mode;
999                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
1000                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
1001                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1002                 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
1003                         session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
1004                 } else {
1005                         session->req_wps_mode = WFD_WPS_MODE_PBC;
1006                 }
1007
1008                 session->state = SESSION_STATE_STARTED;
1009                 wfd_session_timer(session, 1);
1010
1011                 /* Update local device */
1012                 manager->local->wps_mode = event->wps_mode;
1013                 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
1014
1015                 if (session->wps_mode != WFD_WPS_MODE_PBC) {
1016                         char peer_mac_address[MACSTR_LEN+1] = {0, };
1017
1018                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1019                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1020                                                      "Connection",
1021                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1022                                                                             WFD_EVENT_CONNECTION_WPS_REQ,
1023                                                                             peer_mac_address));
1024                         if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
1025                                 /* We have to wait until user type PIN using Keypad */
1026                                 break;
1027                         }
1028                 }
1029
1030                 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
1031                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
1032                         res = wfd_session_wps(session);
1033                 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
1034                         WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
1035                         res = wfd_session_join(session);
1036                 } else {
1037                         WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
1038                         res = wfd_session_connect(session);
1039                 }
1040
1041                 if (res < 0)
1042                         _wfd_notify_session_failed(manager, event->dev_addr);
1043         }
1044         break;
1045         case WFD_OEM_EVENT_GO_NEG_REQ:
1046         {
1047                 if (!session) {
1048                         session = wfd_create_session(manager, event->dev_addr,
1049                                         event->wps_mode, SESSION_DIRECTION_INCOMING);
1050                         if (!session) {
1051                                 WDS_LOGE("Failed to create session");//LCOV_EXCL_LINE
1052                                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
1053                                 break;
1054                         }
1055
1056                         session->type = SESSION_TYPE_NORMAL;
1057                         session->state = SESSION_STATE_GO_NEG;
1058                         wfd_session_timer(session, 1);
1059                         wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
1060                         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
1061
1062                         if (manager->autoconnection == TRUE) {
1063                                 /**
1064                                  * TODO: Add autoconnection peer matching logic.
1065                                  */
1066                                 /**
1067                                  * In autoconnection mode, connection request notification
1068                                  * should not be sent to library.
1069                                  */
1070                                 res  = wfd_session_connect(session);
1071                         } else {
1072                                 char peer_mac_address[MACSTR_LEN+1] = {0, };
1073                                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1074                                 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1075                                                              "Connection",
1076                                                              g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1077                                                                            WFD_EVENT_CONNECTION_REQ,
1078                                                                            peer_mac_address));
1079                         }
1080                 } else {
1081                         /* Sometimes, Provision Discovery response is not received.
1082                          * At this time, connection should be triggered by GO Negotiation request event */
1083                         if (session->direction == SESSION_DIRECTION_OUTGOING) {
1084                                 if (session->wps_mode == WFD_WPS_MODE_KEYPAD && session->wps_pin[0] == '\0')
1085                                         break;
1086                                 res = wfd_session_connect(session);
1087                         } else {
1088                                 /**
1089                                  * TODO: Add autoconnection peer matching logic.
1090                                  */
1091                                 /**
1092                                  * In autoconnection mode, MT should not send GO Nego Req
1093                                  * before receiving the GO Nego Req from peer (MO).
1094                                  */
1095                                 if (manager->autoconnection == TRUE)
1096                                         res  = wfd_session_connect(session);
1097                         }
1098                         if (res < 0)
1099                                 _wfd_notify_session_failed(manager, event->dev_addr);
1100                 }
1101         }
1102         break;
1103         case WFD_OEM_EVENT_GO_NEG_DONE:
1104         {
1105                 if (!session) {
1106                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1107                                         MAC2SECSTR(event->dev_addr));
1108                         break;
1109                 } else {
1110                         manager->local->dev_role = event->dev_role;
1111                         session->state = SESSION_STATE_WPS;
1112                 }
1113         }
1114         break;
1115         case WFD_OEM_EVENT_WPS_DONE:
1116         {
1117                 if (!session) {
1118                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1119                                         MAC2SECSTR(event->dev_addr));
1120                         break;
1121                 } else {
1122                         session->state = SESSION_STATE_KEY_NEG;
1123                 }
1124         }
1125         break;
1126         case WFD_OEM_EVENT_STA_CONNECTED:
1127         {
1128                 if (!session) {
1129                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1130                                         MAC2SECSTR(event->dev_addr));
1131                         break;
1132                 } else {
1133                         session->state = SESSION_STATE_COMPLETED;
1134                 }
1135         }
1136                 break;
1137         case WFD_OEM_EVENT_ASP_PROV_START:
1138         {
1139                 int req_wps_mode = WFD_WPS_MODE_NONE;
1140
1141                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1142                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
1143                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1144                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
1145                 else
1146                         req_wps_mode = WFD_WPS_MODE_P2PS;
1147
1148                 session = wfd_create_session(manager, event->dev_addr,
1149                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
1150                 if (!session) {
1151                         WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1152                                                         MAC2SECSTR(event->dev_addr));
1153                         break;
1154                 }
1155
1156                 /* Update session */
1157                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1158                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1159
1160                 session->state = SESSION_STATE_STARTED;
1161                 wfd_session_timer(session, 1);
1162         }
1163                 break;
1164         case WFD_OEM_EVENT_ASP_PROV_DONE:
1165         {
1166                 int req_wps_mode = WFD_WPS_MODE_NONE;
1167
1168                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1169                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
1170                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1171                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
1172                 else
1173                         req_wps_mode = WFD_WPS_MODE_P2PS;
1174
1175                 session = (wfd_session_s*) manager->session;
1176                 if (!session) {
1177                         session = wfd_create_session(manager, event->dev_addr,
1178                                         req_wps_mode, SESSION_DIRECTION_INCOMING);
1179                         if (!session) {
1180                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1181                                                                 MAC2SECSTR(event->dev_addr));
1182                                 break;
1183                         }
1184                         session->state = SESSION_STATE_STARTED;
1185                         wfd_session_timer(session, 1);
1186                 }
1187         }
1188                 break;
1189         default:
1190                 break;
1191         }
1192         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
1193         return 0;
1194 }