52c046cdb7ebb479e451bb5f3615276593b242a0
[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
299         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
300         return 0;
301 }
302
303 int wfd_session_start(wfd_session_s *session)
304 {
305         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
306         wfd_manager_s *manager = wfd_get_manager();
307         wfd_device_s *peer = NULL;
308         int join = 0;
309         int res = 0;
310
311         if (!session) {
312                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
313                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
314                 return -1;
315         }
316
317         if (session->state > SESSION_STATE_STARTED) {
318                 WDS_LOGE("Invalid session state(%d)", session->state);
319                 return -1;
320         }
321
322         /* Check: Invitation Received in Incomming case ->
323          * send prov_disc join
324          *
325          * Check: User select peer to connect with in Outgoing case ->
326          * send prov_disc wps_mode */
327
328         wfd_oem_stop_scan(manager->oem_ops);
329
330         session->state = SESSION_STATE_STARTED;
331         peer = session->peer;
332         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
333                 join = 1;
334         res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
335                                         session->req_wps_mode, join);
336         if (res < 0) {
337                 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
338                                                                         MAC2SECSTR(peer->dev_addr));
339                 wfd_destroy_session(manager);
340                 /* TODO: send notification to App */
341                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
342                 return -1;
343         }
344
345         wfd_session_timer(session, 1);
346
347         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
348         return 0;
349 }
350
351 int wfd_session_asp_session_start(wfd_session_s *session, wfd_oem_asp_prov_s *params)
352 {
353         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
354
355         wfd_manager_s *manager = wfd_get_manager();
356         int res = 0;
357
358         if (session == NULL || params == NULL) {
359                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
360                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
361                 return -1;
362         }
363
364         if (session->state > SESSION_STATE_STARTED) {
365                 WDS_LOGE("Invalid session state(%d)", session->state);
366                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
367                 return -1;
368         }
369
370         res = wfd_oem_asp_prov_disc_req(manager->oem_ops, params);
371         if (res < 0) {
372                 WDS_LOGD("Failed to send ASP provision discovery request to peer");//LCOV_EXCL_LINE
373                 wfd_destroy_session(manager);
374                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
375                 return -1;
376         }
377
378         session->state = SESSION_STATE_STARTED;
379         session->session_id = params->session_id;
380         memcpy(session->session_mac, params->session_mac, MACADDR_LEN);
381         memcpy(session->service_mac, params->service_mac, MACADDR_LEN);
382         wfd_session_timer(session, 1);
383
384         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
385         return 0;
386 }
387
388 #if 0
389 int wfd_session_stop(wfd_session_s *session)
390 {
391         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
392         wfd_manager_s *manager = wfd_get_manager();
393         wfd_device_s *peer = NULL;
394         int res = 0;
395
396         if (!session) {
397                 WDS_LOGE("Invalid parameter");
398                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
399                 return -1;
400         }
401
402         if (session->state > SESSION_STATE_CREATED) {
403                 peer = session->peer;
404                 if (session->direction == SESSION_DIRECTION_INCOMING)
405                         res  = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
406                 else if (session->direction == SESSION_DIRECTION_OUTGOING)
407                         res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
408
409                         if (res < 0) {
410                         WDS_LOGE("Failed to reject or cancel connection");
411                         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
412                         return -1;
413                 }
414         }
415
416         session->state = SESSION_STATE_STOPPED;
417         wfd_destroy_session(manager);
418
419         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
420         return 0;
421 }
422 #endif
423
424 /* In case of incomming session, when user accept connection request, this function should be called.
425  * In case of outgoing session, when prov_disc response arrived, this function should be called.
426  * Even though peer is GO, we can use this function, which can decide using join itself.
427  */
428 int wfd_session_connect(wfd_session_s *session)
429 {
430         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
431         wfd_manager_s *manager = wfd_get_manager();
432         wfd_oem_conn_param_s param;
433         wfd_device_s *peer = NULL;
434         int res = 0;
435
436         if (!session) {
437                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
438                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
439                 return -1;
440         }
441
442         if (session->state > SESSION_STATE_GO_NEG) {
443                 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
444                 return -1;
445         }
446
447         session->state = SESSION_STATE_GO_NEG;
448         peer = session->peer;
449
450         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
451         param.wps_mode = session->wps_mode;
452         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
453                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
454         param.go_intent = session->go_intent;
455         if (peer->display.availability)
456                 param.go_intent = manager->go_intent_per_type[manager->local->display.type];
457         param.freq = session->freq;
458         if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
459                 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
460
461         if (session->wps_pin[0] != '\0')
462                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
463
464         /* To connect with windows phone,set go_intent value to 2.
465         *  As windows phone does not connect when local device act as GO.
466         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
467         *  WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
468         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
469         */
470          if ((peer->pri_dev_type == 1) ||
471                                  ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
472                 param.go_intent = 2;
473                 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
474          }
475
476         WDS_LOGD("connection go_intent: %d", param.go_intent);
477         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
478         if (res < 0) {
479                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
480                 wfd_destroy_session(manager);
481                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
482                 return -1;
483         }
484
485         wfd_session_timer(session, 1);
486
487         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
488         return 0;
489 }
490
491 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
492 {
493         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
494         wfd_manager_s *manager = wfd_get_manager();
495         int res = 0;
496
497         if (!session || !session->peer) {
498                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
499                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
500                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
501         }
502
503         if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
504                 WDS_LOGE("Peer is not included in this session");//LCOV_EXCL_LINE
505                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
506         }
507
508         if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
509                 res = wfd_oem_wps_cancel(manager->oem_ops);
510         else
511                 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
512
513         if (res < 0) {
514                 WDS_LOGE("Failed to cancel connection");//LCOV_EXCL_LINE
515                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
516         }
517
518         wfd_destroy_session(manager);
519
520         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
521         return 0;
522 }
523
524 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
525 {
526         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
527         wfd_manager_s *manager = wfd_get_manager();
528         wfd_device_s *peer = NULL;
529         int res = 0;
530
531         if (!session || !manager) {
532                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
533                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
534                 return -1;
535         }
536
537         /* Invite received case state is just created */
538         if (session->state < SESSION_STATE_CREATED ||
539                 session->state >= SESSION_STATE_STOPPED) {
540                 WDS_LOGE("Session state is Invalid [%d]", session->state);
541                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
542                 return -1;
543         }
544
545         /*
546          * TODO: check session status and do proper work
547          * for example, reject prov_disc, reject nego, stop wps, etc.
548          *
549          */
550
551         peer = session->peer;
552
553         if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
554                 res = wfd_oem_wps_cancel(manager->oem_ops);
555         else
556                 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
557         if (res < 0) {
558                 WDS_LOGE("Failed to reject connection");//LCOV_EXCL_LINE
559                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
560                 return -1;
561         }
562
563         wfd_destroy_session(manager);
564         /* TODO: send notification to App */
565
566         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
567         return 0;
568 }
569
570 int wfd_session_join(wfd_session_s *session)
571 {
572         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
573         wfd_manager_s *manager = wfd_get_manager();
574         wfd_oem_conn_param_s param;
575         wfd_device_s *peer = NULL;
576         int res = 0;
577
578         if (!session) {
579                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
580                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
581                 return -1;
582         }
583
584         session->state = SESSION_STATE_WPS;
585         peer = session->peer;
586
587         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
588         param.wps_mode = session->wps_mode;
589         if (peer->dev_role == WFD_DEV_ROLE_GO)
590                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
591         param.go_intent = session->go_intent;
592         param.freq = session->freq;
593         g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
594
595         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
596         if (res < 0) {
597                 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
598                 wfd_destroy_session(manager);
599                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
600                 return -1;
601         }
602
603         wfd_session_timer(session, 1);
604
605         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
606         return 0;
607 }
608
609 int wfd_session_invite(wfd_session_s *session)
610 {
611         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
612         wfd_manager_s *manager = wfd_get_manager();
613         wfd_oem_invite_param_s param;
614         wfd_device_s *peer = NULL;
615         wfd_group_s *group = NULL;
616         int res = 0;
617
618         if (!session) {
619                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
620                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
621                 return -1;
622         }
623
624         if (session->state > SESSION_STATE_CREATED) {
625                 WDS_LOGE("Invalid session state(%d)", session->state);
626                 return -1;
627         }
628
629         peer = session->peer;
630         group = (wfd_group_s*) manager->group;
631
632         memset(&param, 0x00, sizeof(wfd_oem_invite_param_s));
633         param.ifname = g_strdup(group->ifname);
634         memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
635
636         WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
637                                 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
638
639         res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, &param);
640         if (res < 0) {
641                 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
642                 wfd_destroy_session(manager);
643                 g_free(param.ifname);
644                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
645                 return -1;
646         }
647
648         wfd_session_timer(session, 1);
649         g_free(param.ifname);
650
651         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
652         return 0;
653 }
654
655 int wfd_session_wps(wfd_session_s *session)
656 {
657         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
658         wfd_manager_s *manager = wfd_get_manager();
659         wfd_device_s *peer = NULL;
660         int res = 0;
661
662         if (!session) {
663                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
664                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
665                 return -1;
666         }
667
668         if (session->state > SESSION_STATE_WPS) {
669                 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
670                 return -1;
671         }
672
673         session->state = SESSION_STATE_WPS;
674         peer = session->peer;
675
676         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
677                 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
678                 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
679         } else {
680                 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
681                 wfd_oem_conn_param_s param;
682                 memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
683                 param.wps_mode = session->wps_mode;
684                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
685                 param.freq = session->freq;     /* currently not used */
686                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
687                 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
688         }
689         if (res < 0) {
690                 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
691                 wfd_destroy_session(manager);
692                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
693                 return -1;
694         }
695
696         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
697         return 0;
698 }
699
700 /* In case of incomming session, when user accept connection request, this function should be called.
701  * In case of outgoing session, when prov_disc response arrived, this function should be called.
702  * Even though peer is GO, we can use this function, which can decide using join itself.
703  */
704 int wfd_session_asp_connect(wfd_session_s *session, int role)
705 {
706         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
707         wfd_manager_s *manager = wfd_get_manager();
708         wfd_oem_conn_param_s param;
709         wfd_device_s *peer = NULL;
710         int res = 0;
711
712         if (!session) {
713                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
714                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
715                 return -1;
716         }
717
718         if (session->state >= SESSION_STATE_GO_NEG) {
719                 WDS_LOGE("Session already starting GO Negotiation");//LCOV_EXCL_LINE
720                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
721                 return -1;
722         }
723
724         if (role == WFD_OEM_ASP_SESSION_ROLE_GO) {
725                 session->state = SESSION_STATE_WPS;
726                 return 0;
727         } else {
728                 session->state = SESSION_STATE_GO_NEG;
729         }
730
731         peer = session->peer;
732
733         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
734         param.wps_mode = session->wps_mode;
735         if (role == 2)
736                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
737         param.go_intent = session->go_intent;
738         param.freq = session->freq;
739         param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
740
741         if (session->wps_pin[0] != '\0')
742                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
743
744         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
745         if (res < 0) {
746                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
747                 wfd_destroy_session(manager);
748                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
749                 return -1;
750         }
751
752         wfd_session_timer(session, 1);
753
754         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
755         return 0;
756 }
757
758 /* In case of incomming session, when user accept connection request, this function should be called.
759  * In case of outgoing session, when prov_disc response arrived, this function should be called.
760  * Even though peer is GO, we can use this function, which can decide using join itself.
761  */
762 int wfd_session_asp_persistent_connect(wfd_session_s *session, int persist_group_id)
763 {
764         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
765         wfd_manager_s *manager = wfd_get_manager();
766         wfd_oem_group_param_s param;
767         int res = 0;
768
769         if (!session) {
770                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
771                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
772                 return -1;
773         }
774
775         if (session->state > SESSION_STATE_GO_NEG) {
776                 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
777                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
778                 return -1;
779         }
780
781         session->state = SESSION_STATE_WPS;
782
783         memset(&param, 0x0, sizeof(param));
784         param.persistent = 2;
785         param.persistent_group_id = persist_group_id;
786
787         res = wfd_oem_create_group(manager->oem_ops, &param);
788         if (res < 0) {
789                 WDS_LOGD("Failed to create persistent group for ASP");//LCOV_EXCL_LINE
790                 wfd_destroy_session(manager);
791                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
792                 return -1;
793         }
794
795         wfd_session_timer(session, 1);
796
797         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
798         return 0;
799 }
800
801 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
802 {
803         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
804         wfd_device_s *peer = NULL;
805
806         if (!session) {
807                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
808                 return NULL;
809         }
810
811         peer = session->peer;
812
813         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
814         return peer;
815 }
816
817 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
818 {
819         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
820         wfd_device_s *peer = NULL;
821
822         if (!session || !session->peer) {
823                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
824                 return NULL;
825         }
826
827         peer = session->peer;
828
829         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
830         return peer->dev_addr;
831 }
832
833 #if 0
834 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
835 {
836         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
837
838         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
839         return 0;
840 }
841
842 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
843 {
844         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
845
846         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
847         return 0;
848 }
849
850 int wfd_session_set_freq(wfd_session_s *session, int freq)
851 {
852         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
853
854         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
855         return 0;
856 }
857
858 int wfd_session_get_state(wfd_session_s *session)
859 {
860         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
861
862         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
863         return 0;
864 }
865
866 int wfd_session_set_state(wfd_session_s *session, int state)
867 {
868         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
869
870         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
871         return 0;
872 }
873 #endif
874
875 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
876 {
877         __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
878         wfd_session_s *session = NULL;
879         int res = 0;
880
881         if (!manager || !event) {
882                 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
883                 return -1;
884         }
885
886         WDS_LOGD("event ID [%d]", event->event_id);
887         session = manager->session;
888
889         switch (event->event_id) {
890         case WFD_OEM_EVENT_PROV_DISC_REQ:
891         {
892                 int req_wps_mode = WFD_WPS_MODE_NONE;
893
894                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
895                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
896                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
897                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
898                 else
899                         req_wps_mode = WFD_WPS_MODE_PBC;
900
901                 /* Only peer initiated connection or invitation session can be allowed */
902                 if (session) {
903                         if (session->type != SESSION_TYPE_INVITE) {
904                                 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
905                                                                 MAC2SECSTR(event->dev_addr));
906                                 break;
907                         }
908                         WDS_LOGD("=====> session already exist. (invitation session)");//LCOV_EXCL_LINE
909                         if (session->state > SESSION_STATE_WPS) {
910                                 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
911                                 break;
912                         }
913
914                         session->req_wps_mode = req_wps_mode;
915                         session->wps_mode = event->wps_mode;
916                 } else {
917                         session = wfd_create_session(manager, event->dev_addr,
918                                                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
919                         if (!session) {
920                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
921                                                                 MAC2SECSTR(event->dev_addr));
922                                 break;
923                         }
924                 }
925
926                 /* Update session */
927                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
928                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
929
930                 session->state = SESSION_STATE_STARTED;
931                 if (session->type == SESSION_TYPE_INVITE)
932                         WDS_LOGD("Invitation session");//LCOV_EXCL_LINE
933                 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
934                         session->type = SESSION_TYPE_JOIN;
935                 else
936                         session->type = SESSION_TYPE_NORMAL;
937
938                 wfd_session_timer(session, 1);
939
940                 /* Update local device */
941                 manager->local->wps_mode = event->wps_mode;
942
943                 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
944                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
945
946                 if (session->type == SESSION_TYPE_INVITE) {
947                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
948                         if (session->wps_mode != WFD_WPS_MODE_PBC) {
949                                 char peer_mac_address[MACSTR_LEN+1] = {0, };
950
951                                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
952                                 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
953                                                              "Connection",
954                                                              g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
955                                                                                     WFD_EVENT_CONNECTION_WPS_REQ,
956                                                                                     peer_mac_address));
957                                 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
958                                         /* We have to wait until user type PIN using Keypad */
959                                         break;
960                                 }
961                         }
962                         res = wfd_session_wps(session);
963                         if (res < 0)
964                                 _wfd_notify_session_failed(manager, event->dev_addr);
965                 } else {
966                         char peer_mac_address[MACSTR_LEN+1] = {0, };
967
968                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
969                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
970                                                      "Connection",
971                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
972                                                                             WFD_EVENT_CONNECTION_REQ,
973                                                                             peer_mac_address));
974                 }
975         }
976         break;
977         case WFD_OEM_EVENT_PROV_DISC_RESP:
978         {
979                 if (!session) {         /* TODO: check validity of Event */
980                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
981                                                                                 MAC2SECSTR(event->dev_addr));
982                         break;
983                 }
984
985                 if (session->state > SESSION_STATE_STARTED) {
986                         WDS_LOGE("Unexpected event. Session is already started");//LCOV_EXCL_LINE
987                         break;
988                 }
989
990                 if (session->type == SESSION_TYPE_INVITE) {
991                         WDS_LOGE("Session type is invite, ignore provision discovery response");//LCOV_EXCL_LINE
992                         break;
993                 }
994
995                 /* Update session */
996                 session->wps_mode = event->wps_mode;
997                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
998                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
999                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1000                 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
1001                         session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
1002                 } else {
1003                         session->req_wps_mode = WFD_WPS_MODE_PBC;
1004                 }
1005
1006                 session->state = SESSION_STATE_STARTED;
1007                 wfd_session_timer(session, 1);
1008
1009                 /* Update local device */
1010                 manager->local->wps_mode = event->wps_mode;
1011                 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
1012
1013                 if (session->wps_mode != WFD_WPS_MODE_PBC) {
1014                         char peer_mac_address[MACSTR_LEN+1] = {0, };
1015
1016                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1017                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1018                                                      "Connection",
1019                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1020                                                                             WFD_EVENT_CONNECTION_WPS_REQ,
1021                                                                             peer_mac_address));
1022                         if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
1023                                 /* We have to wait until user type PIN using Keypad */
1024                                 break;
1025                         }
1026                 }
1027
1028                 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
1029                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
1030                         res = wfd_session_wps(session);
1031                 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
1032                         WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
1033                         res = wfd_session_join(session);
1034                 } else {
1035                         WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
1036                         res = wfd_session_connect(session);
1037                 }
1038
1039                 if (res < 0)
1040                         _wfd_notify_session_failed(manager, event->dev_addr);
1041         }
1042         break;
1043         case WFD_OEM_EVENT_GO_NEG_REQ:
1044         {
1045                 if (!session) {
1046                         session = wfd_create_session(manager, event->dev_addr,
1047                                         event->wps_mode, SESSION_DIRECTION_INCOMING);
1048                         if (!session) {
1049                                 WDS_LOGE("Failed to create session");//LCOV_EXCL_LINE
1050                                 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
1051                                 break;
1052                         }
1053
1054                         session->type = SESSION_TYPE_NORMAL;
1055                         session->state = SESSION_STATE_GO_NEG;
1056                         wfd_session_timer(session, 1);
1057                         wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
1058                         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
1059
1060                         if (manager->autoconnection == TRUE) {
1061                                 /**
1062                                  * TODO: Add autoconnection peer matching logic.
1063                                  */
1064                                 /**
1065                                  * In autoconnection mode, connection request notification
1066                                  * should not be sent to library.
1067                                  */
1068                                 res  = wfd_session_connect(session);
1069                         } else {
1070                                 char peer_mac_address[MACSTR_LEN+1] = {0, };
1071                                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1072                                 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1073                                                              "Connection",
1074                                                              g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1075                                                                            WFD_EVENT_CONNECTION_REQ,
1076                                                                            peer_mac_address));
1077                         }
1078                 } else {
1079                         /* Sometimes, Provision Discovery response is not received.
1080                          * At this time, connection should be triggered by GO Negotiation request event */
1081                         if (session->direction == SESSION_DIRECTION_OUTGOING) {
1082                                 if (session->wps_mode == WFD_WPS_MODE_KEYPAD && session->wps_pin[0] == '\0')
1083                                         break;
1084                                 res = wfd_session_connect(session);
1085                         } else {
1086                                 /**
1087                                  * TODO: Add autoconnection peer matching logic.
1088                                  */
1089                                 /**
1090                                  * In autoconnection mode, MT should not send GO Nego Req
1091                                  * before receiving the GO Nego Req from peer (MO).
1092                                  */
1093                                 if (manager->autoconnection == TRUE)
1094                                         res  = wfd_session_connect(session);
1095                         }
1096                         if (res < 0)
1097                                 _wfd_notify_session_failed(manager, event->dev_addr);
1098                 }
1099         }
1100         break;
1101         case WFD_OEM_EVENT_GO_NEG_DONE:
1102         {
1103                 if (!session) {
1104                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1105                                         MAC2SECSTR(event->dev_addr));
1106                         break;
1107                 } else {
1108                         manager->local->dev_role = event->dev_role;
1109                         session->state = SESSION_STATE_WPS;
1110                 }
1111         }
1112         break;
1113         case WFD_OEM_EVENT_WPS_DONE:
1114         {
1115                 if (!session) {
1116                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1117                                         MAC2SECSTR(event->dev_addr));
1118                         break;
1119                 } else {
1120                         session->state = SESSION_STATE_KEY_NEG;
1121                 }
1122         }
1123         break;
1124         case WFD_OEM_EVENT_STA_CONNECTED:
1125         {
1126                 if (!session) {
1127                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1128                                         MAC2SECSTR(event->dev_addr));
1129                         break;
1130                 } else {
1131                         session->state = SESSION_STATE_COMPLETED;
1132                 }
1133         }
1134                 break;
1135         case WFD_OEM_EVENT_ASP_PROV_START:
1136         {
1137                 int req_wps_mode = WFD_WPS_MODE_NONE;
1138
1139                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1140                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
1141                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1142                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
1143                 else
1144                         req_wps_mode = WFD_WPS_MODE_P2PS;
1145
1146                 session = wfd_create_session(manager, event->dev_addr,
1147                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
1148                 if (!session) {
1149                         WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1150                                                         MAC2SECSTR(event->dev_addr));
1151                         break;
1152                 }
1153
1154                 /* Update session */
1155                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1156                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1157
1158                 session->state = SESSION_STATE_STARTED;
1159                 wfd_session_timer(session, 1);
1160         }
1161                 break;
1162         case WFD_OEM_EVENT_ASP_PROV_DONE:
1163         {
1164                 int req_wps_mode = WFD_WPS_MODE_NONE;
1165
1166                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1167                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
1168                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1169                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
1170                 else
1171                         req_wps_mode = WFD_WPS_MODE_P2PS;
1172
1173                 session = (wfd_session_s*) manager->session;
1174                 if (!session) {
1175                         session = wfd_create_session(manager, event->dev_addr,
1176                                         req_wps_mode, SESSION_DIRECTION_INCOMING);
1177                         if (!session) {
1178                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1179                                                                 MAC2SECSTR(event->dev_addr));
1180                                 break;
1181                         }
1182                         session->state = SESSION_STATE_STARTED;
1183                         wfd_session_timer(session, 1);
1184                 }
1185         }
1186                 break;
1187         default:
1188                 break;
1189         }
1190         __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
1191         return 0;
1192 }