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