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