2 * Network Configuration Module
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * This file implements wifi direct session functions.
23 * @file wifi-direct-session.c
24 * @author Gibyoung Kim (lastkgb.kim@samsung.com)
33 #include <wifi-direct.h>
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"
47 static gboolean _session_timeout_cb(gpointer *user_data)
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;
56 WDS_LOGE("Invalid parameter");
59 session->connecting_120 = 0;
61 WDS_LOGD("Session timer expired");
63 peer_addr = wfd_session_get_peer_addr(session);
65 memset(¬i, 0x0, sizeof(wifi_direct_client_noti_s));
66 noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_RSP;
67 noti.error = WIFI_DIRECT_ERROR_CONNECTION_CANCELED;
69 g_snprintf(noti.param1, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
70 wfd_client_send_event(manager, ¬i);
72 wfd_session_cancel(session, peer_addr);
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);
78 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
79 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
82 __WDS_LOG_FUNC_EXIT__;
86 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
88 __WDS_LOG_FUNC_ENTER__;
89 wifi_direct_client_noti_s noti;
90 memset(¬i, 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));
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);
99 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
100 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
103 wfd_client_send_event(manager, ¬i);
104 __WDS_LOG_FUNC_EXIT__;
107 int wfd_session_timer(wfd_session_s *session, int start)
109 __WDS_LOG_FUNC_ENTER__;
112 WDS_LOGE("Invalid parameter");
113 __WDS_LOG_FUNC_EXIT__;
118 if (!session->connecting_120)
119 session->connecting_120 = 1;
121 if (session->timer > 0) {
122 WDS_LOGE("Session timer already started");
123 __WDS_LOG_FUNC_EXIT__;
126 session->timer = g_timeout_add(120000,
127 (GSourceFunc) _session_timeout_cb,
129 WDS_LOGD("Session timer started");
131 session->connecting_120 = 0;
132 if (session->timer > 0) {
133 g_source_remove(session->timer);
135 WDS_LOGD("Session timer stoped");
139 __WDS_LOG_FUNC_EXIT__;
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)
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;
151 if (!data || !peer_addr) {
152 WDS_LOGE("Invalid parameter");
153 __WDS_LOG_FUNC_EXIT__;
157 WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
159 if (manager->session) {
160 WDS_LOGE("Session already exist");
164 session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
166 WDS_LOGE("Failed to allocate memory for session");
167 __WDS_LOG_FUNC_EXIT__;
171 peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
173 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
175 __WDS_LOG_FUNC_EXIT__;
178 peer->state = WFD_PEER_STATE_CONNECTING;
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;
187 session->wps_mode = wps_mode;
188 session->direction = direction;
189 session->state = SESSION_STATE_CREATED;
191 manager->session = session;
192 manager->local->wps_mode = session->wps_mode;
194 if (peer->dev_role == WFD_DEV_ROLE_GO &&
195 manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
196 char *generated_pin = NULL;
197 session->wps_mode = WFD_WPS_MODE_DISPLAY;
198 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
200 if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
201 WDS_LOGE("Failed to generate pin");
203 __WDS_LOG_FUNC_EXIT__;
207 g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
208 g_free(generated_pin);
211 if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
212 manager->local->dev_role = WFD_DEV_ROLE_GC;
214 __WDS_LOG_FUNC_EXIT__;
218 int wfd_destroy_session(void *data)
220 __WDS_LOG_FUNC_ENTER__;
221 wfd_manager_s *manager = (wfd_manager_s*) data;
222 wfd_session_s *session = NULL;
223 wfd_device_s *peer = NULL;
226 WDS_LOGE("Invalid parameter");
230 session = (wfd_session_s*) manager->session;
232 WDS_LOGE("Session not found"); // self prevent 13029
235 wfd_session_timer(session, 0);
236 peer = session->peer;
239 if (session->state == SESSION_STATE_COMPLETED)
240 peer->state = WFD_PEER_STATE_CONNECTED;
242 peer->state = WFD_PEER_STATE_DISCOVERED;
244 WDS_LOGE("Peer not found");
248 manager->session = NULL;
249 manager->local->wps_mode = WFD_WPS_MODE_PBC;
250 manager->autoconnection = 0;
251 memset(manager->auto_pin, 0x0, PINSTR_LEN);
252 if (manager->local->dev_role == WFD_DEV_ROLE_GC)
253 manager->local->dev_role = WFD_DEV_ROLE_NONE;
255 __WDS_LOG_FUNC_EXIT__;
259 int wfd_session_start(wfd_session_s *session)
261 __WDS_LOG_FUNC_ENTER__;
262 wfd_manager_s *manager = wfd_get_manager();
263 wfd_device_s *peer = NULL;
268 WDS_LOGE("Invalid parameter");
269 __WDS_LOG_FUNC_EXIT__;
273 if (session->state > SESSION_STATE_STARTED) {
274 WDS_LOGE("Invalid session state(%d)", session->state);
278 // Check: Invitation Received in Incomming case -> send prov_disc join
279 // Check: User select peer to connect with in Outgoing case -> send prov_disc wps_mdde
281 wfd_oem_stop_scan(manager->oem_ops);
283 session->state = SESSION_STATE_STARTED;
284 peer = session->peer;
285 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
287 res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
288 session->req_wps_mode, join);
290 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
291 MAC2SECSTR(peer->dev_addr));
292 wfd_destroy_session(manager);
293 // TODO: send notification to App
294 __WDS_LOG_FUNC_EXIT__;
298 wfd_session_timer(session, 1);
300 __WDS_LOG_FUNC_EXIT__;
305 int wfd_session_stop(wfd_session_s *session)
307 __WDS_LOG_FUNC_ENTER__;
308 wfd_manager_s *manager = wfd_get_manager();
309 wfd_device_s *peer = NULL;
313 WDS_LOGE("Invalid parameter");
314 __WDS_LOG_FUNC_EXIT__;
318 if (session->state > SESSION_STATE_CREATED) {
319 peer = session->peer;
320 if (session->direction == SESSION_DIRECTION_INCOMING) {
321 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
322 } else if (session->direction == SESSION_DIRECTION_OUTGOING) {
323 res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
326 WDS_LOGE("Failed to reject or cancel connection");
327 __WDS_LOG_FUNC_EXIT__;
332 session->state = SESSION_STATE_STOPPED;
333 wfd_destroy_session(manager);
335 __WDS_LOG_FUNC_EXIT__;
340 /* In case of incomming session, when user accept connection request, this function should be called.
341 * In case of outgoing session, when prov_disc response arrived, this function should be called.
342 * Even though peer is GO, we can use this function, which can decide using join itself.
344 int wfd_session_connect(wfd_session_s *session)
346 __WDS_LOG_FUNC_ENTER__;
347 wfd_manager_s *manager = wfd_get_manager();
348 wfd_oem_conn_param_s param;
349 wfd_device_s *peer = NULL;
353 WDS_LOGE("Invalid parameter");
354 __WDS_LOG_FUNC_EXIT__;
358 if (session->state > SESSION_STATE_GO_NEG) {
359 WDS_LOGE("Session already finished GO Negotiation");
363 wfd_oem_stop_scan(manager->oem_ops);
365 session->state = SESSION_STATE_GO_NEG;
366 peer = session->peer;
368 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
369 param.wps_mode = session->wps_mode;
370 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
371 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
372 param.go_intent = session->go_intent;
373 param.freq = session->freq;
374 if(manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
375 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
377 if (session->wps_pin[0] != '\0') {
378 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
381 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
383 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
384 wfd_destroy_session(manager);
385 __WDS_LOG_FUNC_EXIT__;
389 wfd_session_timer(session, 1);
391 __WDS_LOG_FUNC_EXIT__;
395 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
397 __WDS_LOG_FUNC_ENTER__;
398 wfd_manager_s *manager = wfd_get_manager();
401 if (!session || !session->peer) {
402 WDS_LOGE("Invalid parameter");
403 __WDS_LOG_FUNC_EXIT__;
404 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
407 if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
408 WDS_LOGE("Peer is not included in this session");
409 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
412 if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
413 res = wfd_oem_wps_cancel(manager->oem_ops);
415 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
418 WDS_LOGE("Failed to cancel connection");
419 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
422 wfd_destroy_session(manager);
424 __WDS_LOG_FUNC_EXIT__;
428 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
430 __WDS_LOG_FUNC_ENTER__;
431 wfd_manager_s *manager = wfd_get_manager();
432 wfd_device_s *peer = NULL;
435 if (!session || !manager) {
436 WDS_LOGE("Invalid parameter");
437 __WDS_LOG_FUNC_EXIT__;
441 /* Invite received case state is just created */
442 if (session->state < SESSION_STATE_CREATED ||
443 session->state >= SESSION_STATE_STOPPED) {
444 WDS_LOGE("Session state is Invalid [%d]", session->state);
445 __WDS_LOG_FUNC_EXIT__;
450 * TODO: check session status and do proper work
451 * for example, reject prov_disc, reject nego, stop wps, etc.
455 peer = session->peer;
457 if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
458 res = wfd_oem_wps_cancel(manager->oem_ops);
460 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
462 WDS_LOGE("Failed to reject connection");
463 __WDS_LOG_FUNC_EXIT__;
467 wfd_destroy_session(manager);
468 // TODO: send notification to App
470 __WDS_LOG_FUNC_EXIT__;
474 int wfd_session_join(wfd_session_s *session)
476 __WDS_LOG_FUNC_ENTER__;
477 wfd_manager_s *manager = wfd_get_manager();
478 wfd_oem_conn_param_s param;
479 wfd_device_s *peer = NULL;
483 WDS_LOGE("Invalid parameter");
484 __WDS_LOG_FUNC_EXIT__;
488 session->state = SESSION_STATE_WPS;
489 peer = session->peer;
491 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
492 param.wps_mode = session->wps_mode;
493 if (peer->dev_role == WFD_DEV_ROLE_GO)
494 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
495 param.go_intent = session->go_intent;
496 param.freq = session->freq;
497 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
499 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
501 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
502 wfd_destroy_session(manager);
503 __WDS_LOG_FUNC_EXIT__;
507 wfd_session_timer(session, 1);
509 __WDS_LOG_FUNC_EXIT__;
513 int wfd_session_invite(wfd_session_s *session)
515 __WDS_LOG_FUNC_ENTER__;
516 wfd_manager_s *manager = wfd_get_manager();
517 wfd_oem_invite_param_s param;
518 wfd_device_s *peer = NULL;
519 wfd_group_s *group = NULL;
523 WDS_LOGE("Invalid parameter");
524 __WDS_LOG_FUNC_EXIT__;
528 if (session->state > SESSION_STATE_CREATED) {
529 WDS_LOGE("Invalid session state(%d)", session->state);
533 peer = session->peer;
534 group = (wfd_group_s*) manager->group;
536 memset(¶m, 0x00, sizeof(wfd_oem_invite_param_s));
537 param.ifname = strdup(group->ifname);
538 memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
540 WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
541 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
543 res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, ¶m);
545 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
546 wfd_destroy_session(manager);
547 __WDS_LOG_FUNC_EXIT__;
551 wfd_session_timer(session, 1);
553 __WDS_LOG_FUNC_EXIT__;
557 int wfd_session_wps(wfd_session_s *session)
559 __WDS_LOG_FUNC_ENTER__;
560 wfd_manager_s *manager = wfd_get_manager();
561 wfd_device_s *peer = NULL;
565 WDS_LOGE("Invalid parameter");
566 __WDS_LOG_FUNC_EXIT__;
570 if (session->state > SESSION_STATE_WPS) {
571 WDS_LOGE("Session already starts WPS");
575 session->state = SESSION_STATE_WPS;
576 peer = session->peer;
578 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
579 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
580 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
582 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
583 wfd_oem_conn_param_s param;
584 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
585 param.wps_mode = session->wps_mode;
586 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
587 param.freq = session->freq; // currently not used
588 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
589 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
592 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
593 wfd_destroy_session(manager);
594 __WDS_LOG_FUNC_EXIT__;
598 __WDS_LOG_FUNC_EXIT__;
602 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
604 __WDS_LOG_FUNC_ENTER__;
605 wfd_device_s *peer = NULL;
608 WDS_LOGE("Invalid parameter");
612 peer = session->peer;
614 __WDS_LOG_FUNC_EXIT__;
618 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
620 __WDS_LOG_FUNC_ENTER__;
621 wfd_device_s *peer = NULL;
623 if (!session || !session->peer) {
624 WDS_LOGE("Invalid parameter");
628 peer = session->peer;
630 __WDS_LOG_FUNC_EXIT__;
631 return peer->dev_addr;
635 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
637 __WDS_LOG_FUNC_ENTER__;
639 __WDS_LOG_FUNC_EXIT__;
643 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
645 __WDS_LOG_FUNC_ENTER__;
647 __WDS_LOG_FUNC_EXIT__;
651 int wfd_session_set_freq(wfd_session_s *session, int freq)
653 __WDS_LOG_FUNC_ENTER__;
655 __WDS_LOG_FUNC_EXIT__;
659 int wfd_session_get_state(wfd_session_s *session)
661 __WDS_LOG_FUNC_ENTER__;
663 __WDS_LOG_FUNC_EXIT__;
667 int wfd_session_set_state(wfd_session_s *session, int state)
669 __WDS_LOG_FUNC_ENTER__;
671 __WDS_LOG_FUNC_EXIT__;
676 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
678 __WDS_LOG_FUNC_ENTER__;
679 wfd_session_s *session = NULL;
682 if (!manager || !event) {
683 WDS_LOGE("Invalid parameter");
687 WDS_LOGD("event ID [%d]", event->event_id);
688 session = manager->session;
690 switch (event->event_id) {
691 case WFD_OEM_EVENT_PROV_DISC_REQ:
693 int req_wps_mode = WFD_WPS_MODE_NONE;
695 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
696 req_wps_mode = WFD_WPS_MODE_KEYPAD;
697 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
698 req_wps_mode = WFD_WPS_MODE_DISPLAY;
700 req_wps_mode = WFD_WPS_MODE_PBC;
703 /* Only peer initiated connection or invitation session can be allowed */
705 if (session->type != SESSION_TYPE_INVITE) {
706 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
707 MAC2SECSTR(event->dev_addr));
710 WDS_LOGD("=====> session already exist. (invitation session)");
711 session->req_wps_mode = req_wps_mode;
712 session->wps_mode = event->wps_mode;
714 session = wfd_create_session(manager, event->dev_addr,
715 req_wps_mode, SESSION_DIRECTION_INCOMING);
717 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
718 MAC2SECSTR(event->dev_addr));
724 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
725 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
727 session->state = SESSION_STATE_STARTED;
728 if (session->type == SESSION_TYPE_INVITE) {
729 WDS_LOGD("Invitation session");
730 } else if (WFD_DEV_ROLE_GO == manager->local->dev_role) {
731 session->type = SESSION_TYPE_JOIN;
733 session->type = SESSION_TYPE_NORMAL;
735 wfd_session_timer(session, 1);
737 /* Update local device */
738 manager->local->wps_mode = event->wps_mode;
740 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
742 if (session->type == SESSION_TYPE_INVITE) {
743 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
744 if (session->wps_mode != WFD_WPS_MODE_PBC) {
745 wifi_direct_client_noti_s noti;
746 memset(¬i, 0x0, sizeof(wifi_direct_client_noti_s));
747 noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_WPS_REQ;
748 g_snprintf(noti.param1, sizeof(noti.param1), MACSTR, MAC2STR(event->dev_addr));
749 wfd_client_send_event(manager, ¬i);
750 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
751 /* We have to wait until user type PIN using Keypad */
755 res = wfd_session_wps(session);
757 _wfd_notify_session_failed(manager, event->dev_addr);
759 wifi_direct_client_noti_s noti;
760 memset(¬i, 0x0, sizeof(wifi_direct_client_noti_s));
761 noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_REQ;
762 noti.error = WIFI_DIRECT_ERROR_NONE;
763 snprintf(noti.param1, sizeof(noti.param1), MACSTR, MAC2STR(event->dev_addr));
764 wfd_client_send_event(manager, ¬i);
768 case WFD_OEM_EVENT_PROV_DISC_RESP:
770 if (!session) { // TODO: check validity of Event
771 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
772 MAC2SECSTR(event->dev_addr));
776 if (session->state > SESSION_STATE_STARTED) {
777 WDS_LOGE("Unexpected event. Session is already started");
781 if (session->type == SESSION_TYPE_INVITE) {
782 WDS_LOGE("Session type is invite, ignore provision discovery response");
787 session->wps_mode = event->wps_mode;
788 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
789 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
790 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
791 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
792 session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
794 session->req_wps_mode = WFD_WPS_MODE_PBC;
796 session->state = SESSION_STATE_STARTED;
797 wfd_session_timer(session, 1);
799 /* Update local device */
800 manager->local->wps_mode = event->wps_mode;
801 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
803 if (session->wps_mode != WFD_WPS_MODE_PBC) {
804 wifi_direct_client_noti_s noti;
805 memset(¬i, 0x0, sizeof(wifi_direct_client_noti_s));
806 noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_WPS_REQ;
807 g_snprintf(noti.param1, sizeof(noti.param1), MACSTR, MAC2STR(event->dev_addr));
808 wfd_client_send_event(manager, ¬i);
809 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
810 /* We have to wait until user type PIN using Keypad */
815 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
816 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
817 res = wfd_session_wps(session);
818 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
819 WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
820 res = wfd_session_join(session);
822 WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
823 res = wfd_session_connect(session);
827 _wfd_notify_session_failed(manager, event->dev_addr);
829 case WFD_OEM_EVENT_GO_NEG_REQ:
831 // TODO: check whether connection is started by negotiation not by prov_disc
832 WDS_LOGE("Unexpected event. Session not exist [peer: " MACSECSTR "]",
833 MAC2SECSTR(event->dev_addr));
836 /* Sometimes, Provision Discovery response is not received.
837 * At this time, connection should be triggered by GO Negotiation request event */
838 if (session->direction == SESSION_DIRECTION_OUTGOING) {
839 res = wfd_session_connect(session);
841 /* In autoconnection mode, MT should not send GO Nego Req
842 before receiving the GO Nego Req from peer (MO). */
843 if (manager->autoconnection == TRUE)
844 res = wfd_session_connect(session);
847 _wfd_notify_session_failed(manager, event->dev_addr);
850 case WFD_OEM_EVENT_GO_NEG_DONE:
852 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
853 MAC2SECSTR(event->dev_addr));
856 session->state = SESSION_STATE_WPS;
860 case WFD_OEM_EVENT_WPS_DONE:
862 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
863 MAC2SECSTR(event->dev_addr));
866 session->state = SESSION_STATE_KEY_NEG;
870 case WFD_OEM_EVENT_CONNECTED:
873 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
874 MAC2SECSTR(event->dev_addr));
877 wfd_group_s *group = manager->group;
879 group = wfd_create_pending_group(manager, event->intf_addr);
881 WDS_LOGE("Failed to create pending group");
884 manager->group = group;
885 } else { // multiconnection, additional client connected
886 WDS_LOGE("Unexpected event. Group already exist");
887 //wfd_group_add_member(manager, event->intf_addr, peer->dev_addr);
890 session->state = SESSION_STATE_COMPLETED;
894 case WFD_OEM_EVENT_STA_CONNECTED:
896 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
897 MAC2SECSTR(event->dev_addr));
900 session->state = SESSION_STATE_COMPLETED;
907 __WDS_LOG_FUNC_EXIT__;