[wifi-direct-manager]Merge Tizen 2.4 for sync
[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
31 #include <glib.h>
32
33 #include <wifi-direct.h>
34
35 #include "wifi-direct-ipc.h"
36 #include "wifi-direct-manager.h"
37 #include "wifi-direct-oem.h"
38 #include "wifi-direct-peer.h"
39 #include "wifi-direct-group.h"
40 #include "wifi-direct-oem.h"
41 #include "wifi-direct-util.h"
42 #include "wifi-direct-session.h"
43 #include "wifi-direct-client.h"
44 #include "wifi-direct-state.h"
45
46
47 static gboolean _session_timeout_cb(gpointer *user_data)
48 {
49         __WDS_LOG_FUNC_ENTER__;
50         wfd_manager_s *manager = wfd_get_manager();
51         wfd_session_s *session = (wfd_session_s*) manager->session;
52         wifi_direct_client_noti_s noti;
53         unsigned char *peer_addr = NULL;
54
55         if (!session) {
56                 WDS_LOGE("Invalid parameter");
57                 return FALSE;
58         }
59         session->connecting_120 = 0;
60         session->timer = 0;
61         WDS_LOGD("Session timer expired");
62
63         peer_addr = wfd_session_get_peer_addr(session);
64
65         memset(&noti, 0x0, sizeof(wifi_direct_client_noti_s));
66         noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_RSP;
67         noti.error = WIFI_DIRECT_ERROR_CONNECTION_CANCELED;
68         if(peer_addr != NULL)
69                 g_snprintf(noti.param1, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
70         wfd_client_send_event(manager, &noti);
71
72         wfd_session_cancel(session, peer_addr);
73
74         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
75                 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
76                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
77         } else {
78                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
79                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
80         }
81
82         __WDS_LOG_FUNC_EXIT__;
83         return FALSE;
84 }
85
86 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
87 {
88         __WDS_LOG_FUNC_ENTER__;
89         wifi_direct_client_noti_s noti;
90         memset(&noti, 0x0, sizeof(wifi_direct_client_noti_s));
91         noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_RSP;
92         noti.error = WIFI_DIRECT_ERROR_CONNECTION_FAILED;
93         snprintf(noti.param1, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
94
95         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
96                 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
97                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
98         } else {
99                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
100                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
101         }
102
103         wfd_client_send_event(manager, &noti);
104         __WDS_LOG_FUNC_EXIT__;
105 }
106
107 int wfd_session_timer(wfd_session_s *session, int start)
108 {
109         __WDS_LOG_FUNC_ENTER__;
110
111         if (!session) {
112                 WDS_LOGE("Invalid parameter");
113                 __WDS_LOG_FUNC_EXIT__;
114                 return -1;
115         }
116
117         if (start) {
118                 if (!session->connecting_120)
119                         session->connecting_120 = 1;
120
121                 if (session->timer > 0) {
122                         WDS_LOGE("Session timer already started");
123                         __WDS_LOG_FUNC_EXIT__;
124                         return -1;
125                 }
126                 session->timer = g_timeout_add(120000,
127                                                         (GSourceFunc) _session_timeout_cb,
128                                                         session);
129                 WDS_LOGD("Session timer started");
130         } else {
131                 session->connecting_120 = 0;
132                 if (session->timer > 0) {
133                         g_source_remove(session->timer);
134                         session->timer = 0;
135                         WDS_LOGD("Session timer stoped");
136                 }
137         }
138
139         __WDS_LOG_FUNC_EXIT__;
140         return 0;
141 }
142
143 // Check the session instance which has same peer address, before using this function
144 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
145 {
146         __WDS_LOG_FUNC_ENTER__;
147         wfd_manager_s *manager = (wfd_manager_s*) data;
148         wfd_session_s *session = NULL;
149         wfd_device_s *peer = NULL;
150
151         if (!data || !peer_addr) {
152                 WDS_LOGE("Invalid parameter");
153                 __WDS_LOG_FUNC_EXIT__;
154                 return NULL;
155         }
156
157         WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
158
159         if (manager->session) {
160                 WDS_LOGE("Session already exist");
161                 return NULL;
162         }
163
164         session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
165         if (!session) {
166                 WDS_LOGE("Failed to allocate memory for session");
167                 __WDS_LOG_FUNC_EXIT__;
168                 return NULL;
169         }
170
171         peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
172         if (!peer) {
173                 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
174                 g_free(session);
175                 __WDS_LOG_FUNC_EXIT__;
176                 return NULL;
177         }
178         peer->state = WFD_PEER_STATE_CONNECTING;
179
180         session->peer = peer;
181         session->req_wps_mode = wps_mode;
182         if (wps_mode == WFD_WPS_MODE_DISPLAY)
183                 session->wps_mode = WFD_WPS_MODE_KEYPAD;
184         else if (wps_mode == WFD_WPS_MODE_KEYPAD)
185                 session->wps_mode = WFD_WPS_MODE_DISPLAY;
186         else
187                 session->wps_mode = wps_mode;
188         session->direction = direction;
189         session->state = SESSION_STATE_CREATED;
190
191         manager->session = session;
192         manager->local->wps_mode = session->wps_mode;
193         if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
194                 manager->local->dev_role = WFD_DEV_ROLE_GC;
195
196         __WDS_LOG_FUNC_EXIT__;
197         return session;
198 }
199
200 int wfd_destroy_session(void *data)
201 {
202         __WDS_LOG_FUNC_ENTER__;
203         wfd_manager_s *manager = (wfd_manager_s*) data;
204         wfd_session_s *session = NULL;
205         wfd_device_s *peer = NULL;
206
207         if (!manager) {
208                 WDS_LOGE("Invalid parameter");
209                 return -1;
210         }
211
212         session = (wfd_session_s*) manager->session;
213         if (!session) {
214                 WDS_LOGE("Session not found");  // self prevent 13029
215                 return -1;
216         }
217         wfd_session_timer(session, 0);
218         peer = session->peer;
219
220         if(peer) {
221                 if (session->state == SESSION_STATE_COMPLETED)
222                         peer->state = WFD_PEER_STATE_CONNECTED;
223                 else
224                         peer->state = WFD_PEER_STATE_DISCOVERED;
225         } else {
226                 WDS_LOGE("Peer not found");
227         }
228
229         g_free(session);
230         manager->session = NULL;
231         manager->local->wps_mode = WFD_WPS_MODE_PBC;
232         manager->autoconnection = 0;
233         memset(manager->auto_pin, 0x0, PINSTR_LEN);
234         if (manager->local->dev_role == WFD_DEV_ROLE_GC)
235                 manager->local->dev_role = WFD_DEV_ROLE_NONE;
236
237         __WDS_LOG_FUNC_EXIT__;
238         return 0;
239 }
240
241 int wfd_session_start(wfd_session_s *session)
242 {
243         __WDS_LOG_FUNC_ENTER__;
244         wfd_manager_s *manager = wfd_get_manager();
245         wfd_device_s *peer = NULL;
246         int join = 0;
247         int res = 0;
248
249         if (!session) {
250                 WDS_LOGE("Invalid parameter");
251                 __WDS_LOG_FUNC_EXIT__;
252                 return -1;
253         }
254
255         if (session->state > SESSION_STATE_STARTED) {
256                 WDS_LOGE("Invalid session state(%d)", session->state);
257                 return -1;
258         }
259
260         // Check: Invitation Received in Incomming case -> send prov_disc join
261         // Check: User select peer to connect with in Outgoing case -> send prov_disc wps_mdde
262
263         wfd_oem_stop_scan(manager->oem_ops);
264
265         session->state = SESSION_STATE_STARTED;
266         peer = session->peer;
267         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
268                 join = 1;
269         res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
270                                         session->req_wps_mode, join);
271         if (res < 0) {
272                 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
273                                                                         MAC2SECSTR(peer->dev_addr));
274                 wfd_destroy_session(manager);
275                 // TODO: send notification to App
276                 __WDS_LOG_FUNC_EXIT__;
277                 return -1;
278         }
279
280         wfd_session_timer(session, 1);
281
282         __WDS_LOG_FUNC_EXIT__;
283         return 0;
284 }
285
286 #if 0
287 int wfd_session_stop(wfd_session_s *session)
288 {
289         __WDS_LOG_FUNC_ENTER__;
290         wfd_manager_s *manager = wfd_get_manager();
291         wfd_device_s *peer = NULL;
292         int res = 0;
293
294         if (!session) {
295                 WDS_LOGE("Invalid parameter");
296                 __WDS_LOG_FUNC_EXIT__;
297                 return -1;
298         }
299
300         if (session->state > SESSION_STATE_CREATED) {
301                 peer = session->peer;
302                 if (session->direction == SESSION_DIRECTION_INCOMING) {
303                         res  = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
304                 } else if (session->direction == SESSION_DIRECTION_OUTGOING) {
305                         res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
306                 }
307                 if (res < 0) {
308                         WDS_LOGE("Failed to reject or cancel connection");
309                         __WDS_LOG_FUNC_EXIT__;
310                         return -1;
311                 }
312         }
313
314         session->state = SESSION_STATE_STOPPED;
315         wfd_destroy_session(manager);
316
317         __WDS_LOG_FUNC_EXIT__;
318         return 0;
319 }
320 #endif
321
322 /* In case of incomming session, when user accept connection request, this function should be called.
323  * In case of outgoing session, when prov_disc response arrived, this function should be called.
324  * Even though peer is GO, we can use this function, which can decide using join itself.
325  */
326 int wfd_session_connect(wfd_session_s *session)
327 {
328         __WDS_LOG_FUNC_ENTER__;
329         wfd_manager_s *manager = wfd_get_manager();
330         wfd_oem_conn_param_s param;
331         wfd_device_s *peer = NULL;
332         int res = 0;
333
334         if (!session) {
335                 WDS_LOGE("Invalid parameter");
336                 __WDS_LOG_FUNC_EXIT__;
337                 return -1;
338         }
339
340         if (session->state > SESSION_STATE_GO_NEG) {
341                 WDS_LOGE("Session already finished GO Negotiation");
342                 return -1;
343         }
344
345         wfd_oem_stop_scan(manager->oem_ops);
346
347         session->state = SESSION_STATE_GO_NEG;
348         peer = session->peer;
349
350         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
351         param.wps_mode = session->wps_mode;
352         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
353                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
354         param.go_intent = session->go_intent;
355         param.freq = session->freq;
356         if(manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
357                 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
358
359         if (session->wps_pin[0] != '\0') {
360                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
361         }
362
363         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
364         if (res < 0) {
365                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
366                 wfd_destroy_session(manager);
367                 __WDS_LOG_FUNC_EXIT__;
368                 return -1;
369         }
370
371         wfd_session_timer(session, 1);
372
373         __WDS_LOG_FUNC_EXIT__;
374         return 0;
375 }
376
377 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
378 {
379         __WDS_LOG_FUNC_ENTER__;
380         wfd_manager_s *manager = wfd_get_manager();
381         int res = 0;
382
383         if (!session || !session->peer) {
384                 WDS_LOGE("Invalid parameter");
385                 __WDS_LOG_FUNC_EXIT__;
386                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
387         }
388
389         if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
390                 WDS_LOGE("Peer is not included in this session");
391                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
392         }
393
394         if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
395                 res = wfd_oem_wps_cancel(manager->oem_ops);
396         else
397                 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
398
399         if (res < 0) {
400                 WDS_LOGE("Failed to cancel connection");
401                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
402         }
403
404         wfd_destroy_session(manager);
405
406         __WDS_LOG_FUNC_EXIT__;
407         return 0;
408 }
409
410 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
411 {
412         __WDS_LOG_FUNC_ENTER__;
413         wfd_manager_s *manager = wfd_get_manager();
414         wfd_device_s *peer = NULL;
415         int res = 0;
416
417         if (!session || !manager) {
418                 WDS_LOGE("Invalid parameter");
419                 __WDS_LOG_FUNC_EXIT__;
420                 return -1;
421         }
422
423         /* Invite received case state is just created */
424         if (session->state < SESSION_STATE_CREATED ||
425                 session->state >= SESSION_STATE_STOPPED) {
426                 WDS_LOGE("Session state is Invalid [%d]", session->state);
427                 __WDS_LOG_FUNC_EXIT__;
428                 return -1;
429         }
430
431         /*
432          * TODO: check session status and do proper work
433          * for example, reject prov_disc, reject nego, stop wps, etc.
434          *
435          */
436
437         peer = session->peer;
438
439         if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
440                 res = wfd_oem_wps_cancel(manager->oem_ops);
441         else
442                 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
443         if (res < 0) {
444                 WDS_LOGE("Failed to reject connection");
445                 __WDS_LOG_FUNC_EXIT__;
446                 return -1;
447         }
448
449         wfd_destroy_session(manager);
450         // TODO: send notification to App
451
452         __WDS_LOG_FUNC_EXIT__;
453         return 0;
454 }
455
456 int wfd_session_join(wfd_session_s *session)
457 {
458         __WDS_LOG_FUNC_ENTER__;
459         wfd_manager_s *manager = wfd_get_manager();
460         wfd_oem_conn_param_s param;
461         wfd_device_s *peer = NULL;
462         int res = 0;
463
464         if (!session) {
465                 WDS_LOGE("Invalid parameter");
466                 __WDS_LOG_FUNC_EXIT__;
467                 return -1;
468         }
469
470         session->state = SESSION_STATE_WPS;
471         peer = session->peer;
472
473         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
474         param.wps_mode = session->wps_mode;
475         if (peer->dev_role == WFD_DEV_ROLE_GO)
476                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
477         param.go_intent = session->go_intent;
478         param.freq = session->freq;
479         g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
480
481         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
482         if (res < 0) {
483                 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
484                 wfd_destroy_session(manager);
485                 __WDS_LOG_FUNC_EXIT__;
486                 return -1;
487         }
488
489         wfd_session_timer(session, 1);
490
491         __WDS_LOG_FUNC_EXIT__;
492         return 0;
493 }
494
495 int wfd_session_invite(wfd_session_s *session)
496 {
497         __WDS_LOG_FUNC_ENTER__;
498         wfd_manager_s *manager = wfd_get_manager();
499         wfd_oem_invite_param_s param;
500         wfd_device_s *peer = NULL;
501         wfd_group_s *group = NULL;
502         int res = 0;
503
504         if (!session) {
505                 WDS_LOGE("Invalid parameter");
506                 __WDS_LOG_FUNC_EXIT__;
507                 return -1;
508         }
509
510         if (session->state > SESSION_STATE_CREATED) {
511                 WDS_LOGE("Invalid session state(%d)", session->state);
512                 return -1;
513         }
514
515         peer = session->peer;
516         group = (wfd_group_s*) manager->group;
517
518         memset(&param, 0x00, sizeof(wfd_oem_invite_param_s));
519         param.ifname = strdup(group->ifname);
520         memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
521
522         WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
523                                 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
524
525         res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, &param);
526         if (res < 0) {
527                 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
528                 wfd_destroy_session(manager);
529                 __WDS_LOG_FUNC_EXIT__;
530                 return -1;
531         }
532
533         wfd_session_timer(session, 1);
534
535         __WDS_LOG_FUNC_EXIT__;
536         return 0;
537 }
538
539 int wfd_session_wps(wfd_session_s *session)
540 {
541         __WDS_LOG_FUNC_ENTER__;
542         wfd_manager_s *manager = wfd_get_manager();
543         wfd_device_s *peer = NULL;
544         int res = 0;
545
546         if (!session) {
547                 WDS_LOGE("Invalid parameter");
548                 __WDS_LOG_FUNC_EXIT__;
549                 return -1;
550         }
551
552         if (session->state > SESSION_STATE_WPS) {
553                 WDS_LOGE("Session already starts WPS");
554                 return -1;
555         }
556
557         session->state = SESSION_STATE_WPS;
558         peer = session->peer;
559
560         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
561                 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
562                 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
563         } else {
564                 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
565                 wfd_oem_conn_param_s param;
566                 memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
567                 param.wps_mode = session->wps_mode;
568                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
569                 param.freq = session->freq;     // currently not used
570                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
571                 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
572         }
573         if (res < 0) {
574                 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
575                 wfd_destroy_session(manager);
576                 __WDS_LOG_FUNC_EXIT__;
577                 return -1;
578         }
579
580         __WDS_LOG_FUNC_EXIT__;
581         return 0;
582 }
583
584 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
585 {
586         __WDS_LOG_FUNC_ENTER__;
587         wfd_device_s *peer = NULL;
588
589         if (!session) {
590                 WDS_LOGE("Invalid parameter");
591                 return NULL;
592         }
593
594         peer = session->peer;
595
596         __WDS_LOG_FUNC_EXIT__;
597         return peer;
598 }
599
600 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
601 {
602         __WDS_LOG_FUNC_ENTER__;
603         wfd_device_s *peer = NULL;
604
605         if (!session || !session->peer) {
606                 WDS_LOGE("Invalid parameter");
607                 return NULL;
608         }
609
610         peer = session->peer;
611
612         __WDS_LOG_FUNC_EXIT__;
613         return peer->dev_addr;
614 }
615
616 #if 0
617 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
618 {
619         __WDS_LOG_FUNC_ENTER__;
620
621         __WDS_LOG_FUNC_EXIT__;
622         return 0;
623 }
624
625 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
626 {
627         __WDS_LOG_FUNC_ENTER__;
628
629         __WDS_LOG_FUNC_EXIT__;
630         return 0;
631 }
632
633 int wfd_session_set_freq(wfd_session_s *session, int freq)
634 {
635         __WDS_LOG_FUNC_ENTER__;
636
637         __WDS_LOG_FUNC_EXIT__;
638         return 0;
639 }
640
641 int wfd_session_get_state(wfd_session_s *session)
642 {
643         __WDS_LOG_FUNC_ENTER__;
644
645         __WDS_LOG_FUNC_EXIT__;
646         return 0;
647 }
648
649 int wfd_session_set_state(wfd_session_s *session, int state)
650 {
651         __WDS_LOG_FUNC_ENTER__;
652
653         __WDS_LOG_FUNC_EXIT__;
654         return 0;
655 }
656 #endif
657
658 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
659 {
660         __WDS_LOG_FUNC_ENTER__;
661         wfd_session_s *session = NULL;
662         int res = 0;
663
664         if (!manager || !event) {
665                 WDS_LOGE("Invalid parameter");
666                 return -1;
667         }
668
669         WDS_LOGD("event ID [%d]", event->event_id);
670         session = manager->session;
671
672         switch (event->event_id) {
673         case WFD_OEM_EVENT_PROV_DISC_REQ:
674         {
675                 int req_wps_mode = WFD_WPS_MODE_NONE;
676
677                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
678                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
679                 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
680                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
681                 } else {
682                         req_wps_mode = WFD_WPS_MODE_PBC;
683                 }
684
685                 /* Only peer initiated connection or invitation session can be allowed */
686                 if (session) {
687                         if (session->type != SESSION_TYPE_INVITE) {
688                                 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
689                                                                 MAC2SECSTR(event->dev_addr));
690                                 break;
691                         }
692                         WDS_LOGD("=====> session already exist. (invitation session)");
693                 } else {
694                         session = wfd_create_session(manager, event->dev_addr,
695                                                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
696                         if (!session) {
697                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
698                                                                 MAC2SECSTR(event->dev_addr));
699                                 break;
700                         }
701                 }
702
703                 /* Update session */
704                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
705                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
706                 }
707                 session->state = SESSION_STATE_STARTED;
708                 if (session->type == SESSION_TYPE_INVITE) {
709                         WDS_LOGD("Invitation session");
710                 } else if (WFD_DEV_ROLE_GO == manager->local->dev_role) {
711                         session->type = SESSION_TYPE_JOIN;
712                 } else {
713                         session->type = SESSION_TYPE_NORMAL;
714                 }
715                 wfd_session_timer(session, 1);
716
717                 /* Update local device */
718                 manager->local->wps_mode = event->wps_mode;
719
720                 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
721
722                 if (session->type == SESSION_TYPE_INVITE) {
723                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
724                         res = wfd_session_wps(session);
725                         if (res < 0)
726                                 _wfd_notify_session_failed(manager, event->dev_addr);
727                 } else {
728                         wifi_direct_client_noti_s noti;
729                         memset(&noti, 0x0, sizeof(wifi_direct_client_noti_s));
730                         noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_REQ;
731                         noti.error = WIFI_DIRECT_ERROR_NONE;
732                         snprintf(noti.param1, sizeof(noti.param1), MACSTR, MAC2STR(event->dev_addr));
733                         wfd_client_send_event(manager, &noti);
734                 }
735         }
736         break;
737         case WFD_OEM_EVENT_PROV_DISC_RESP:
738         {
739                 if (!session) {         // TODO: check validity of Event
740                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
741                                                                                 MAC2SECSTR(event->dev_addr));
742                         break;
743                 }
744
745                 if (session->state > SESSION_STATE_STARTED) {
746                         WDS_LOGE("Unexpected event. Session is already started");
747                         break;
748                 }
749
750                 /* Update session */
751                 session->wps_mode = event->wps_mode;
752                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
753                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
754                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
755                 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
756                         session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
757                 } else {
758                         session->req_wps_mode = WFD_WPS_MODE_PBC;
759                 }
760                 session->state = SESSION_STATE_STARTED;
761                 wfd_session_timer(session, 1);
762
763                 /* Update local device */
764                 manager->local->wps_mode = event->wps_mode;
765                 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
766
767                 if (session->wps_mode != WFD_WPS_MODE_PBC) {
768                         wifi_direct_client_noti_s noti;
769                         memset(&noti, 0x0, sizeof(wifi_direct_client_noti_s));
770                         noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_WPS_REQ;
771                         g_snprintf(noti.param1, sizeof(noti.param1), MACSTR, MAC2STR(event->dev_addr));
772                         wfd_client_send_event(manager, &noti);
773                         if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
774                                 /* We have to wait until user type PIN using Keypad */
775                                 break;
776                         }
777                 }
778
779                 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
780                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
781                         res = wfd_session_wps(session);
782                 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
783                         WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
784                         res = wfd_session_join(session);
785                 } else {
786                         WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
787                         res = wfd_session_connect(session);
788                 }
789         }
790         if (res < 0)
791                 _wfd_notify_session_failed(manager, event->dev_addr);
792         break;
793         case WFD_OEM_EVENT_GO_NEG_REQ:
794                 if (!session) {
795                         // TODO: check whether connection is started by negotiation not by prov_disc
796                         WDS_LOGE("Unexpected event. Session not exist [peer: " MACSECSTR "]",
797                                                 MAC2SECSTR(event->dev_addr));
798                         break;
799                 } else {
800                         /* Sometimes, Provision Discovery response is not received.
801                          * At this time, connection should be triggered by GO Negotiation request event */
802                         if (session->direction == SESSION_DIRECTION_OUTGOING) {
803                                 res = wfd_session_connect(session);
804                         } else {
805                                 /* In autoconnection mode, MT should not send GO Nego Req
806                                    before receving the GO Nego Req from peer (MO). */
807                                 if (manager->autoconnection == TRUE)
808                                         res  = wfd_session_connect(session);
809                         }
810                         if (res < 0)
811                                 _wfd_notify_session_failed(manager, event->dev_addr);
812                 }
813                 break;
814         case WFD_OEM_EVENT_GO_NEG_DONE:
815                 if (!session) {
816                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
817                                                 MAC2SECSTR(event->dev_addr));
818                         break;
819                 } else {
820                         session->state = SESSION_STATE_WPS;
821                 }
822
823                 break;
824         case WFD_OEM_EVENT_WPS_DONE:
825                 if (!session) {
826                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
827                                                 MAC2SECSTR(event->dev_addr));
828                         break;
829                 } else {
830                         session->state = SESSION_STATE_KEY_NEG;
831                 }
832
833                 break;
834         case WFD_OEM_EVENT_CONNECTED:
835         {
836                 if (!session) {
837                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
838                                                 MAC2SECSTR(event->dev_addr));
839                         break;
840                 } else {
841                         wfd_group_s *group = manager->group;
842                         if (!group) {
843                                 group = wfd_create_pending_group(manager, event->intf_addr);
844                                 if (!group) {
845                                         WDS_LOGE("Failed to create pending group");
846                                         break;
847                                 }
848                                 manager->group = group;
849                         } else {        // multiconnection, additional client connected
850                                 WDS_LOGE("Unexpected event. Group already exist");
851                                 //wfd_group_add_member(manager, event->intf_addr, peer->dev_addr);
852                                 break;
853                         }
854                         session->state = SESSION_STATE_COMPLETED;
855                 }
856         }
857         break;
858         case WFD_OEM_EVENT_STA_CONNECTED:
859                 if (!session) {
860                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
861                                                 MAC2SECSTR(event->dev_addr));
862                         break;
863                 } else {
864                         session->state = SESSION_STATE_COMPLETED;
865                 }
866
867                 break;
868         default:
869                 break;
870         }
871         __WDS_LOG_FUNC_EXIT__;
872         return 0;
873 }