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)
34 #include <wifi-direct.h>
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"
51 static gboolean _session_timeout_cb(gpointer *user_data)
53 __WDS_LOG_FUNC_ENTER__;
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, };
60 WDS_LOGE("Invalid parameter");
63 session->connecting_120 = 0;
65 WDS_LOGD("Session timer expired");
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));
71 g_snprintf(peer_mac_address, MACSTR_LEN, "%s", "");
73 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
75 g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT,
76 WFD_EVENT_CONNECTION_RSP,
79 if (wfd_asp_is_asp_session(session)) {
80 if (session->state < SESSION_STATE_GO_NEG)
81 wfd_asp_connect_status(session->session_mac,
83 ASP_CONNECT_STATUS_REQUEST_FAILED,
86 wfd_asp_connect_status(session->session_mac,
88 ASP_CONNECT_STATUS_GROUP_FORMATION_FAILED,
92 wfd_session_cancel(session, peer_addr);
94 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
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);
100 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
101 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
104 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
105 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
108 __WDS_LOG_FUNC_EXIT__;
112 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
114 __WDS_LOG_FUNC_ENTER__;
115 char peer_mac_address[MACSTR_LEN+1] = {0, };
117 snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
118 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
120 g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_FAILED,
121 WFD_EVENT_CONNECTION_RSP,
126 wfd_session_s *session = manager->session;
127 if (wfd_asp_is_asp_session(session)) {
128 wfd_asp_connect_status(session->session_mac,
130 ASP_CONNECT_STATUS_GROUP_FORMATION_STARTED,
134 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
135 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
136 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
138 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
139 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
142 __WDS_LOG_FUNC_EXIT__;
145 int wfd_session_timer(wfd_session_s *session, int start)
147 __WDS_LOG_FUNC_ENTER__;
150 WDS_LOGE("Invalid parameter");
151 __WDS_LOG_FUNC_EXIT__;
156 if (!session->connecting_120)
157 session->connecting_120 = 1;
159 if (session->timer > 0) {
160 WDS_LOGE("Session timer already started");
161 __WDS_LOG_FUNC_EXIT__;
164 session->timer = g_timeout_add(120000,
165 (GSourceFunc) _session_timeout_cb,
167 WDS_LOGD("Session timer started");
169 session->connecting_120 = 0;
170 if (session->timer > 0) {
171 g_source_remove(session->timer);
173 WDS_LOGD("Session timer stoped");
177 __WDS_LOG_FUNC_EXIT__;
181 /* Check the session instance which has same peer address,
182 * before using this function */
183 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
185 __WDS_LOG_FUNC_ENTER__;
186 wfd_manager_s *manager = (wfd_manager_s*) data;
187 wfd_session_s *session = NULL;
188 wfd_device_s *peer = NULL;
190 if (!data || !peer_addr) {
191 WDS_LOGE("Invalid parameter");
192 __WDS_LOG_FUNC_EXIT__;
196 WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
198 if (manager->session) {
199 WDS_LOGE("Session already exist");
203 session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
205 WDS_LOGE("Failed to allocate memory for session");
206 __WDS_LOG_FUNC_EXIT__;
210 peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
212 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
214 __WDS_LOG_FUNC_EXIT__;
217 peer->state = WFD_PEER_STATE_CONNECTING;
219 session->peer = peer;
220 session->req_wps_mode = wps_mode;
221 if (wps_mode == WFD_WPS_MODE_DISPLAY)
222 session->wps_mode = WFD_WPS_MODE_KEYPAD;
223 else if (wps_mode == WFD_WPS_MODE_KEYPAD)
224 session->wps_mode = WFD_WPS_MODE_DISPLAY;
225 else if (wps_mode == WFD_WPS_MODE_P2PS)
226 session->wps_mode = WFD_WPS_MODE_P2PS;
228 session->wps_mode = wps_mode;
229 session->direction = direction;
230 session->state = SESSION_STATE_CREATED;
232 manager->session = session;
233 manager->local->wps_mode = session->wps_mode;
235 if (peer->dev_role == WFD_DEV_ROLE_GO &&
236 manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
237 char *generated_pin = NULL;
238 session->wps_mode = WFD_WPS_MODE_DISPLAY;
239 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
241 if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
242 WDS_LOGE("Failed to generate pin");
244 __WDS_LOG_FUNC_EXIT__;
248 g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
249 g_free(generated_pin);
252 if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
253 manager->local->dev_role = WFD_DEV_ROLE_GC;
255 __WDS_LOG_FUNC_EXIT__;
259 int wfd_destroy_session(void *data)
261 __WDS_LOG_FUNC_ENTER__;
262 wfd_manager_s *manager = (wfd_manager_s*) data;
263 wfd_session_s *session = NULL;
264 wfd_device_s *peer = NULL;
267 WDS_LOGE("Invalid parameter");
271 session = (wfd_session_s*) manager->session;
273 WDS_LOGE("Session not found"); /* self prevent */
276 wfd_session_timer(session, 0);
277 peer = session->peer;
278 WDS_LOGD("peer :%p", peer);
281 if (session->state == SESSION_STATE_COMPLETED)
282 peer->state = WFD_PEER_STATE_CONNECTED;
284 peer->state = WFD_PEER_STATE_DISCOVERED;
286 WDS_LOGE("Peer not found");
290 manager->session = NULL;
291 manager->local->wps_mode = WFD_WPS_MODE_PBC;
292 manager->autoconnection = 0;
293 memset(manager->auto_pin, 0x0, PINSTR_LEN);
294 if (manager->local->dev_role == WFD_DEV_ROLE_GC)
295 manager->local->dev_role = WFD_DEV_ROLE_NONE;
297 __WDS_LOG_FUNC_EXIT__;
301 int wfd_session_start(wfd_session_s *session)
303 __WDS_LOG_FUNC_ENTER__;
304 wfd_manager_s *manager = wfd_get_manager();
305 wfd_device_s *peer = NULL;
310 WDS_LOGE("Invalid parameter");
311 __WDS_LOG_FUNC_EXIT__;
315 if (session->state > SESSION_STATE_STARTED) {
316 WDS_LOGE("Invalid session state(%d)", session->state);
320 /* Check: Invitation Received in Incomming case ->
321 * send prov_disc join
323 * Check: User select peer to connect with in Outgoing case ->
324 * send prov_disc wps_mode */
326 wfd_oem_stop_scan(manager->oem_ops);
328 session->state = SESSION_STATE_STARTED;
329 peer = session->peer;
330 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
332 res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
333 session->req_wps_mode, join);
335 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
336 MAC2SECSTR(peer->dev_addr));
337 wfd_destroy_session(manager);
338 /* TODO: send notification to App */
339 __WDS_LOG_FUNC_EXIT__;
343 wfd_session_timer(session, 1);
345 __WDS_LOG_FUNC_EXIT__;
349 int wfd_session_asp_session_start(wfd_session_s *session, wfd_oem_asp_prov_s *params)
351 __WDS_LOG_FUNC_ENTER__;
353 wfd_manager_s *manager = wfd_get_manager();
356 if (session == NULL || params == NULL) {
357 WDS_LOGE("Invalid parameter");
358 __WDS_LOG_FUNC_EXIT__;
362 if (session->state > SESSION_STATE_STARTED) {
363 WDS_LOGE("Invalid session state(%d)", session->state);
364 __WDS_LOG_FUNC_EXIT__;
368 res = wfd_oem_asp_prov_disc_req(manager->oem_ops, params);
370 WDS_LOGD("Failed to send ASP provision discovery request to peer");
371 wfd_destroy_session(manager);
372 __WDS_LOG_FUNC_EXIT__;
376 session->state = SESSION_STATE_STARTED;
377 session->session_id = params->session_id;
378 memcpy(session->session_mac, params->session_mac, MACADDR_LEN);
379 memcpy(session->service_mac, params->service_mac, MACADDR_LEN);
380 wfd_session_timer(session, 1);
382 __WDS_LOG_FUNC_EXIT__;
387 int wfd_session_stop(wfd_session_s *session)
389 __WDS_LOG_FUNC_ENTER__;
390 wfd_manager_s *manager = wfd_get_manager();
391 wfd_device_s *peer = NULL;
395 WDS_LOGE("Invalid parameter");
396 __WDS_LOG_FUNC_EXIT__;
400 if (session->state > SESSION_STATE_CREATED) {
401 peer = session->peer;
402 if (session->direction == SESSION_DIRECTION_INCOMING)
403 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
404 else if (session->direction == SESSION_DIRECTION_OUTGOING)
405 res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
408 WDS_LOGE("Failed to reject or cancel connection");
409 __WDS_LOG_FUNC_EXIT__;
414 session->state = SESSION_STATE_STOPPED;
415 wfd_destroy_session(manager);
417 __WDS_LOG_FUNC_EXIT__;
422 /* In case of incomming session, when user accept connection request, this function should be called.
423 * In case of outgoing session, when prov_disc response arrived, this function should be called.
424 * Even though peer is GO, we can use this function, which can decide using join itself.
426 int wfd_session_connect(wfd_session_s *session)
428 __WDS_LOG_FUNC_ENTER__;
429 wfd_manager_s *manager = wfd_get_manager();
430 wfd_oem_conn_param_s param;
431 wfd_device_s *peer = NULL;
435 WDS_LOGE("Invalid parameter");
436 __WDS_LOG_FUNC_EXIT__;
440 if (session->state > SESSION_STATE_GO_NEG) {
441 WDS_LOGE("Session already finished GO Negotiation");
445 session->state = SESSION_STATE_GO_NEG;
446 peer = session->peer;
448 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
449 param.wps_mode = session->wps_mode;
450 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
451 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
452 param.go_intent = session->go_intent;
453 param.freq = session->freq;
454 if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
455 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
457 if (session->wps_pin[0] != '\0')
458 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
460 /* To connect with windows phone,set go_intent value to 2.
461 * As windows phone does not connect when local device act as GO.
462 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
463 * WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
464 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
466 if ((peer->pri_dev_type == 1) ||
467 ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
469 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
472 WDS_LOGD("connection go_intent: %d", param.go_intent);
473 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
475 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
476 wfd_destroy_session(manager);
477 __WDS_LOG_FUNC_EXIT__;
481 wfd_session_timer(session, 1);
483 __WDS_LOG_FUNC_EXIT__;
487 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
489 __WDS_LOG_FUNC_ENTER__;
490 wfd_manager_s *manager = wfd_get_manager();
493 if (!session || !session->peer) {
494 WDS_LOGE("Invalid parameter");
495 __WDS_LOG_FUNC_EXIT__;
496 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
499 if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
500 WDS_LOGE("Peer is not included in this session");
501 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
504 if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
505 res = wfd_oem_wps_cancel(manager->oem_ops);
507 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
510 WDS_LOGE("Failed to cancel connection");
511 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
514 wfd_destroy_session(manager);
516 __WDS_LOG_FUNC_EXIT__;
520 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
522 __WDS_LOG_FUNC_ENTER__;
523 wfd_manager_s *manager = wfd_get_manager();
524 wfd_device_s *peer = NULL;
527 if (!session || !manager) {
528 WDS_LOGE("Invalid parameter");
529 __WDS_LOG_FUNC_EXIT__;
533 /* Invite received case state is just created */
534 if (session->state < SESSION_STATE_CREATED ||
535 session->state >= SESSION_STATE_STOPPED) {
536 WDS_LOGE("Session state is Invalid [%d]", session->state);
537 __WDS_LOG_FUNC_EXIT__;
542 * TODO: check session status and do proper work
543 * for example, reject prov_disc, reject nego, stop wps, etc.
547 peer = session->peer;
549 if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
550 res = wfd_oem_wps_cancel(manager->oem_ops);
552 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
554 WDS_LOGE("Failed to reject connection");
555 __WDS_LOG_FUNC_EXIT__;
559 wfd_destroy_session(manager);
560 /* TODO: send notification to App */
562 __WDS_LOG_FUNC_EXIT__;
566 int wfd_session_join(wfd_session_s *session)
568 __WDS_LOG_FUNC_ENTER__;
569 wfd_manager_s *manager = wfd_get_manager();
570 wfd_oem_conn_param_s param;
571 wfd_device_s *peer = NULL;
575 WDS_LOGE("Invalid parameter");
576 __WDS_LOG_FUNC_EXIT__;
580 session->state = SESSION_STATE_WPS;
581 peer = session->peer;
583 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
584 param.wps_mode = session->wps_mode;
585 if (peer->dev_role == WFD_DEV_ROLE_GO)
586 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
587 param.go_intent = session->go_intent;
588 param.freq = session->freq;
589 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
591 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
593 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
594 wfd_destroy_session(manager);
595 __WDS_LOG_FUNC_EXIT__;
599 wfd_session_timer(session, 1);
601 __WDS_LOG_FUNC_EXIT__;
605 int wfd_session_invite(wfd_session_s *session)
607 __WDS_LOG_FUNC_ENTER__;
608 wfd_manager_s *manager = wfd_get_manager();
609 wfd_oem_invite_param_s param;
610 wfd_device_s *peer = NULL;
611 wfd_group_s *group = NULL;
615 WDS_LOGE("Invalid parameter");
616 __WDS_LOG_FUNC_EXIT__;
620 if (session->state > SESSION_STATE_CREATED) {
621 WDS_LOGE("Invalid session state(%d)", session->state);
625 peer = session->peer;
626 group = (wfd_group_s*) manager->group;
628 memset(¶m, 0x00, sizeof(wfd_oem_invite_param_s));
629 param.ifname = strdup(group->ifname);
630 memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
632 WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
633 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
635 res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, ¶m);
637 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
638 wfd_destroy_session(manager);
639 __WDS_LOG_FUNC_EXIT__;
643 wfd_session_timer(session, 1);
645 __WDS_LOG_FUNC_EXIT__;
649 int wfd_session_wps(wfd_session_s *session)
651 __WDS_LOG_FUNC_ENTER__;
652 wfd_manager_s *manager = wfd_get_manager();
653 wfd_device_s *peer = NULL;
657 WDS_LOGE("Invalid parameter");
658 __WDS_LOG_FUNC_EXIT__;
662 if (session->state > SESSION_STATE_WPS) {
663 WDS_LOGE("Session already starts WPS");
667 session->state = SESSION_STATE_WPS;
668 peer = session->peer;
670 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
671 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
672 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
674 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
675 wfd_oem_conn_param_s param;
676 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
677 param.wps_mode = session->wps_mode;
678 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
679 param.freq = session->freq; /* currently not used */
680 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
681 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
684 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
685 wfd_destroy_session(manager);
686 __WDS_LOG_FUNC_EXIT__;
690 __WDS_LOG_FUNC_EXIT__;
694 /* In case of incomming session, when user accept connection request, this function should be called.
695 * In case of outgoing session, when prov_disc response arrived, this function should be called.
696 * Even though peer is GO, we can use this function, which can decide using join itself.
698 int wfd_session_asp_connect(wfd_session_s *session, int role)
700 __WDS_LOG_FUNC_ENTER__;
701 wfd_manager_s *manager = wfd_get_manager();
702 wfd_oem_conn_param_s param;
703 wfd_device_s *peer = NULL;
707 WDS_LOGE("Invalid parameter");
708 __WDS_LOG_FUNC_EXIT__;
712 if (session->state >= SESSION_STATE_GO_NEG) {
713 WDS_LOGE("Session already starting GO Negotiation");
714 __WDS_LOG_FUNC_EXIT__;
718 if (role == WFD_OEM_ASP_SESSION_ROLE_GO) {
719 session->state = SESSION_STATE_WPS;
722 session->state = SESSION_STATE_GO_NEG;
725 peer = session->peer;
727 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
728 param.wps_mode = session->wps_mode;
730 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
731 param.go_intent = session->go_intent;
732 param.freq = session->freq;
733 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
735 if (session->wps_pin[0] != '\0')
736 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
738 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
740 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
741 wfd_destroy_session(manager);
742 __WDS_LOG_FUNC_EXIT__;
746 wfd_session_timer(session, 1);
748 __WDS_LOG_FUNC_EXIT__;
752 /* In case of incomming session, when user accept connection request, this function should be called.
753 * In case of outgoing session, when prov_disc response arrived, this function should be called.
754 * Even though peer is GO, we can use this function, which can decide using join itself.
756 int wfd_session_asp_persistent_connect(wfd_session_s *session, int persist_group_id)
758 __WDS_LOG_FUNC_ENTER__;
759 wfd_manager_s *manager = wfd_get_manager();
760 wfd_oem_group_param_s param;
764 WDS_LOGE("Invalid parameter");
765 __WDS_LOG_FUNC_EXIT__;
769 if (session->state > SESSION_STATE_GO_NEG) {
770 WDS_LOGE("Session already finished GO Negotiation");
771 __WDS_LOG_FUNC_EXIT__;
775 session->state = SESSION_STATE_WPS;
777 memset(¶m, 0x0, sizeof(param));
778 param.persistent = 2;
779 param.persistent_group_id = persist_group_id;
781 res = wfd_oem_create_group(manager->oem_ops, ¶m);
783 WDS_LOGD("Failed to create persistent group for ASP");
784 wfd_destroy_session(manager);
785 __WDS_LOG_FUNC_EXIT__;
789 wfd_session_timer(session, 1);
791 __WDS_LOG_FUNC_EXIT__;
795 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
797 __WDS_LOG_FUNC_ENTER__;
798 wfd_device_s *peer = NULL;
801 WDS_LOGE("Invalid parameter");
805 peer = session->peer;
807 __WDS_LOG_FUNC_EXIT__;
811 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
813 __WDS_LOG_FUNC_ENTER__;
814 wfd_device_s *peer = NULL;
816 if (!session || !session->peer) {
817 WDS_LOGE("Invalid parameter");
821 peer = session->peer;
823 __WDS_LOG_FUNC_EXIT__;
824 return peer->dev_addr;
828 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
830 __WDS_LOG_FUNC_ENTER__;
832 __WDS_LOG_FUNC_EXIT__;
836 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
838 __WDS_LOG_FUNC_ENTER__;
840 __WDS_LOG_FUNC_EXIT__;
844 int wfd_session_set_freq(wfd_session_s *session, int freq)
846 __WDS_LOG_FUNC_ENTER__;
848 __WDS_LOG_FUNC_EXIT__;
852 int wfd_session_get_state(wfd_session_s *session)
854 __WDS_LOG_FUNC_ENTER__;
856 __WDS_LOG_FUNC_EXIT__;
860 int wfd_session_set_state(wfd_session_s *session, int state)
862 __WDS_LOG_FUNC_ENTER__;
864 __WDS_LOG_FUNC_EXIT__;
869 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
871 __WDS_LOG_FUNC_ENTER__;
872 wfd_session_s *session = NULL;
875 if (!manager || !event) {
876 WDS_LOGE("Invalid parameter");
880 WDS_LOGD("event ID [%d]", event->event_id);
881 session = manager->session;
883 switch (event->event_id) {
884 case WFD_OEM_EVENT_PROV_DISC_REQ:
886 int req_wps_mode = WFD_WPS_MODE_NONE;
888 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
889 req_wps_mode = WFD_WPS_MODE_KEYPAD;
890 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
891 req_wps_mode = WFD_WPS_MODE_DISPLAY;
893 req_wps_mode = WFD_WPS_MODE_PBC;
895 /* Only peer initiated connection or invitation session can be allowed */
897 if (session->type != SESSION_TYPE_INVITE) {
898 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
899 MAC2SECSTR(event->dev_addr));
902 WDS_LOGD("=====> session already exist. (invitation session)");
903 if (session->state > SESSION_STATE_WPS) {
904 WDS_LOGE("Session already starts WPS");
908 session->req_wps_mode = req_wps_mode;
909 session->wps_mode = event->wps_mode;
911 session = wfd_create_session(manager, event->dev_addr,
912 req_wps_mode, SESSION_DIRECTION_INCOMING);
914 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
915 MAC2SECSTR(event->dev_addr));
921 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
922 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
924 session->state = SESSION_STATE_STARTED;
925 if (session->type == SESSION_TYPE_INVITE)
926 WDS_LOGD("Invitation session");
927 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
928 session->type = SESSION_TYPE_JOIN;
930 session->type = SESSION_TYPE_NORMAL;
932 wfd_session_timer(session, 1);
934 /* Update local device */
935 manager->local->wps_mode = event->wps_mode;
937 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
938 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
940 if (session->type == SESSION_TYPE_INVITE) {
941 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
942 if (session->wps_mode != WFD_WPS_MODE_PBC) {
943 char peer_mac_address[MACSTR_LEN+1] = {0, };
945 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
946 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
948 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
949 WFD_EVENT_CONNECTION_WPS_REQ,
951 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
952 /* We have to wait until user type PIN using Keypad */
956 res = wfd_session_wps(session);
958 _wfd_notify_session_failed(manager, event->dev_addr);
960 char peer_mac_address[MACSTR_LEN+1] = {0, };
962 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
963 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
965 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
966 WFD_EVENT_CONNECTION_REQ,
971 case WFD_OEM_EVENT_PROV_DISC_RESP:
973 if (!session) { /* TODO: check validity of Event */
974 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
975 MAC2SECSTR(event->dev_addr));
979 if (session->state > SESSION_STATE_STARTED) {
980 WDS_LOGE("Unexpected event. Session is already started");
984 if (session->type == SESSION_TYPE_INVITE) {
985 WDS_LOGE("Session type is invite, ignore provision discovery response");
990 session->wps_mode = event->wps_mode;
991 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
992 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
993 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
994 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
995 session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
997 session->req_wps_mode = WFD_WPS_MODE_PBC;
1000 session->state = SESSION_STATE_STARTED;
1001 wfd_session_timer(session, 1);
1003 /* Update local device */
1004 manager->local->wps_mode = event->wps_mode;
1005 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
1007 if (session->wps_mode != WFD_WPS_MODE_PBC) {
1008 char peer_mac_address[MACSTR_LEN+1] = {0, };
1010 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1011 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1013 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1014 WFD_EVENT_CONNECTION_WPS_REQ,
1016 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
1017 /* We have to wait until user type PIN using Keypad */
1022 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
1023 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
1024 res = wfd_session_wps(session);
1025 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
1026 WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
1027 res = wfd_session_join(session);
1029 WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
1030 res = wfd_session_connect(session);
1034 _wfd_notify_session_failed(manager, event->dev_addr);
1037 case WFD_OEM_EVENT_GO_NEG_REQ:
1040 session = wfd_create_session(manager, event->dev_addr,
1041 event->wps_mode, SESSION_DIRECTION_INCOMING);
1043 WDS_LOGE("Failed to create session");
1044 __WDS_LOG_FUNC_EXIT__;
1048 session->type = SESSION_TYPE_NORMAL;
1049 session->state = SESSION_STATE_GO_NEG;
1050 wfd_session_timer(session, 1);
1051 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
1052 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
1054 char peer_mac_address[MACSTR_LEN+1] = {0, };
1055 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1056 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1058 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1059 WFD_EVENT_CONNECTION_REQ,
1062 /* Sometimes, Provision Discovery response is not received.
1063 * At this time, connection should be triggered by GO Negotiation request event */
1064 if (session->direction == SESSION_DIRECTION_OUTGOING) {
1065 if (session->wps_mode == WFD_WPS_MODE_KEYPAD && session->wps_pin[0] == '\0')
1067 res = wfd_session_connect(session);
1069 /* In autoconnection mode, MT should not send GO Nego Req
1070 before receiving the GO Nego Req from peer (MO). */
1071 if (manager->autoconnection == TRUE)
1072 res = wfd_session_connect(session);
1075 _wfd_notify_session_failed(manager, event->dev_addr);
1079 case WFD_OEM_EVENT_GO_NEG_DONE:
1082 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1083 MAC2SECSTR(event->dev_addr));
1086 manager->local->dev_role = event->dev_role;
1087 session->state = SESSION_STATE_WPS;
1091 case WFD_OEM_EVENT_WPS_DONE:
1094 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1095 MAC2SECSTR(event->dev_addr));
1098 session->state = SESSION_STATE_KEY_NEG;
1102 case WFD_OEM_EVENT_STA_CONNECTED:
1105 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1106 MAC2SECSTR(event->dev_addr));
1109 session->state = SESSION_STATE_COMPLETED;
1113 case WFD_OEM_EVENT_ASP_PROV_START:
1115 int req_wps_mode = WFD_WPS_MODE_NONE;
1117 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1118 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1119 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1120 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1122 req_wps_mode = WFD_WPS_MODE_P2PS;
1124 session = wfd_create_session(manager, event->dev_addr,
1125 req_wps_mode, SESSION_DIRECTION_INCOMING);
1127 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1128 MAC2SECSTR(event->dev_addr));
1132 /* Update session */
1133 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1134 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1136 session->state = SESSION_STATE_STARTED;
1137 wfd_session_timer(session, 1);
1140 case WFD_OEM_EVENT_ASP_PROV_DONE:
1142 int req_wps_mode = WFD_WPS_MODE_NONE;
1144 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1145 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1146 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1147 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1149 req_wps_mode = WFD_WPS_MODE_P2PS;
1151 session = (wfd_session_s*) manager->session;
1153 session = wfd_create_session(manager, event->dev_addr,
1154 req_wps_mode, SESSION_DIRECTION_INCOMING);
1156 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1157 MAC2SECSTR(event->dev_addr));
1160 session->state = SESSION_STATE_STARTED;
1161 wfd_session_timer(session, 1);
1168 __WDS_LOG_FUNC_EXIT__;