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-state.h"
44 #include "wifi-direct-error.h"
45 #include "wifi-direct-log.h"
46 #include "wifi-direct-dbus.h"
47 #include "wifi-direct-asp.h"
50 static gboolean _session_timeout_cb(gpointer *user_data)
52 __WDS_LOG_FUNC_ENTER__;
53 wfd_manager_s *manager = wfd_get_manager();
54 wfd_session_s *session = (wfd_session_s*) manager->session;
55 unsigned char *peer_addr = NULL;
56 char peer_mac_address[MACSTR_LEN+1] = {0, };
59 WDS_LOGE("Invalid parameter");
62 session->connecting_120 = 0;
64 WDS_LOGD("Session timer expired");
66 peer_addr = wfd_session_get_peer_addr(session);
67 if (peer_addr != NULL)
68 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
70 g_snprintf(peer_mac_address, MACSTR_LEN, "%s", "");
72 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
74 g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT,
75 WFD_EVENT_CONNECTION_RSP,
78 if (wfd_asp_is_asp_session(session)) {
79 if (session->state < SESSION_STATE_GO_NEG)
80 wfd_asp_connect_status(session->session_mac,
82 ASP_CONNECT_STATUS_REQUEST_FAILED,
85 wfd_asp_connect_status(session->session_mac,
87 ASP_CONNECT_STATUS_GROUP_FORMATION_FAILED,
91 wfd_session_cancel(session, peer_addr);
93 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
95 wfd_group_s *group = (wfd_group_s*) manager->group;
96 if (group && wfd_util_is_remove_group_allowed()) {
97 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
99 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
100 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
103 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
104 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
107 __WDS_LOG_FUNC_EXIT__;
111 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
113 __WDS_LOG_FUNC_ENTER__;
114 char peer_mac_address[MACSTR_LEN+1] = {0, };
116 snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
117 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
119 g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_FAILED,
120 WFD_EVENT_CONNECTION_RSP,
125 wfd_session_s *session = manager->session;
126 if (wfd_asp_is_asp_session(session)) {
127 wfd_asp_connect_status(session->session_mac,
129 ASP_CONNECT_STATUS_GROUP_FORMATION_STARTED,
133 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
134 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
135 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
137 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
138 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
141 __WDS_LOG_FUNC_EXIT__;
144 int wfd_session_timer(wfd_session_s *session, int start)
146 __WDS_LOG_FUNC_ENTER__;
149 WDS_LOGE("Invalid parameter");
150 __WDS_LOG_FUNC_EXIT__;
155 if (!session->connecting_120)
156 session->connecting_120 = 1;
158 if (session->timer > 0) {
159 WDS_LOGE("Session timer already started");
160 __WDS_LOG_FUNC_EXIT__;
163 session->timer = g_timeout_add(120000,
164 (GSourceFunc) _session_timeout_cb,
166 WDS_LOGD("Session timer started");
168 session->connecting_120 = 0;
169 if (session->timer > 0) {
170 g_source_remove(session->timer);
172 WDS_LOGD("Session timer stoped");
176 __WDS_LOG_FUNC_EXIT__;
180 /* Check the session instance which has same peer address,
181 * before using this function */
182 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
184 __WDS_LOG_FUNC_ENTER__;
185 wfd_manager_s *manager = (wfd_manager_s*) data;
186 wfd_session_s *session = NULL;
187 wfd_device_s *peer = NULL;
189 if (!data || !peer_addr) {
190 WDS_LOGE("Invalid parameter");
191 __WDS_LOG_FUNC_EXIT__;
195 WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
197 if (manager->session) {
198 WDS_LOGE("Session already exist");
202 session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
204 WDS_LOGE("Failed to allocate memory for session");
205 __WDS_LOG_FUNC_EXIT__;
209 peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
211 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
213 __WDS_LOG_FUNC_EXIT__;
216 peer->state = WFD_PEER_STATE_CONNECTING;
218 session->peer = peer;
219 session->req_wps_mode = wps_mode;
220 if (wps_mode == WFD_WPS_MODE_DISPLAY)
221 session->wps_mode = WFD_WPS_MODE_KEYPAD;
222 else if (wps_mode == WFD_WPS_MODE_KEYPAD)
223 session->wps_mode = WFD_WPS_MODE_DISPLAY;
224 else if (wps_mode == WFD_WPS_MODE_P2PS)
225 session->wps_mode = WFD_WPS_MODE_P2PS;
227 session->wps_mode = wps_mode;
228 session->direction = direction;
229 session->state = SESSION_STATE_CREATED;
231 manager->session = session;
232 manager->local->wps_mode = session->wps_mode;
234 if (peer->dev_role == WFD_DEV_ROLE_GO &&
235 manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
236 char *generated_pin = NULL;
237 session->wps_mode = WFD_WPS_MODE_DISPLAY;
238 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
240 if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
241 WDS_LOGE("Failed to generate pin");
243 __WDS_LOG_FUNC_EXIT__;
247 g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
248 g_free(generated_pin);
251 if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
252 manager->local->dev_role = WFD_DEV_ROLE_GC;
254 __WDS_LOG_FUNC_EXIT__;
258 int wfd_destroy_session(void *data)
260 __WDS_LOG_FUNC_ENTER__;
261 wfd_manager_s *manager = (wfd_manager_s*) data;
262 wfd_session_s *session = NULL;
263 wfd_device_s *peer = NULL;
266 WDS_LOGE("Invalid parameter");
270 session = (wfd_session_s*) manager->session;
272 WDS_LOGE("Session not found"); /* self prevent */
275 wfd_session_timer(session, 0);
276 peer = session->peer;
277 WDS_LOGD("peer :%p", peer);
280 if (session->state == SESSION_STATE_COMPLETED)
281 peer->state = WFD_PEER_STATE_CONNECTED;
283 peer->state = WFD_PEER_STATE_DISCOVERED;
285 WDS_LOGE("Peer not found");
289 manager->session = NULL;
290 manager->local->wps_mode = WFD_WPS_MODE_PBC;
291 manager->autoconnection = 0;
292 memset(manager->auto_pin, 0x0, PINSTR_LEN);
293 if (manager->local->dev_role == WFD_DEV_ROLE_GC)
294 manager->local->dev_role = WFD_DEV_ROLE_NONE;
296 __WDS_LOG_FUNC_EXIT__;
300 int wfd_session_start(wfd_session_s *session)
302 __WDS_LOG_FUNC_ENTER__;
303 wfd_manager_s *manager = wfd_get_manager();
304 wfd_device_s *peer = NULL;
309 WDS_LOGE("Invalid parameter");
310 __WDS_LOG_FUNC_EXIT__;
314 if (session->state > SESSION_STATE_STARTED) {
315 WDS_LOGE("Invalid session state(%d)", session->state);
319 /* Check: Invitation Received in Incomming case ->
320 * send prov_disc join
322 * Check: User select peer to connect with in Outgoing case ->
323 * send prov_disc wps_mode */
325 wfd_oem_stop_scan(manager->oem_ops);
327 session->state = SESSION_STATE_STARTED;
328 peer = session->peer;
329 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
331 res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
332 session->req_wps_mode, join);
334 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
335 MAC2SECSTR(peer->dev_addr));
336 wfd_destroy_session(manager);
337 /* TODO: send notification to App */
338 __WDS_LOG_FUNC_EXIT__;
342 wfd_session_timer(session, 1);
344 __WDS_LOG_FUNC_EXIT__;
348 int wfd_session_asp_session_start(wfd_session_s *session, wfd_oem_asp_prov_s *params)
350 __WDS_LOG_FUNC_ENTER__;
352 wfd_manager_s *manager = wfd_get_manager();
355 if (session == NULL || params == NULL) {
356 WDS_LOGE("Invalid parameter");
357 __WDS_LOG_FUNC_EXIT__;
361 if (session->state > SESSION_STATE_STARTED) {
362 WDS_LOGE("Invalid session state(%d)", session->state);
363 __WDS_LOG_FUNC_EXIT__;
367 res = wfd_oem_asp_prov_disc_req(manager->oem_ops, params);
369 WDS_LOGD("Failed to send ASP provision discovery request to peer");
370 wfd_destroy_session(manager);
371 __WDS_LOG_FUNC_EXIT__;
375 session->state = SESSION_STATE_STARTED;
376 session->session_id = params->session_id;
377 memcpy(session->session_mac, params->session_mac, MACADDR_LEN);
378 memcpy(session->service_mac, params->service_mac, MACADDR_LEN);
379 wfd_session_timer(session, 1);
381 __WDS_LOG_FUNC_EXIT__;
386 int wfd_session_stop(wfd_session_s *session)
388 __WDS_LOG_FUNC_ENTER__;
389 wfd_manager_s *manager = wfd_get_manager();
390 wfd_device_s *peer = NULL;
394 WDS_LOGE("Invalid parameter");
395 __WDS_LOG_FUNC_EXIT__;
399 if (session->state > SESSION_STATE_CREATED) {
400 peer = session->peer;
401 if (session->direction == SESSION_DIRECTION_INCOMING)
402 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
403 else if (session->direction == SESSION_DIRECTION_OUTGOING)
404 res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
407 WDS_LOGE("Failed to reject or cancel connection");
408 __WDS_LOG_FUNC_EXIT__;
413 session->state = SESSION_STATE_STOPPED;
414 wfd_destroy_session(manager);
416 __WDS_LOG_FUNC_EXIT__;
421 /* In case of incomming session, when user accept connection request, this function should be called.
422 * In case of outgoing session, when prov_disc response arrived, this function should be called.
423 * Even though peer is GO, we can use this function, which can decide using join itself.
425 int wfd_session_connect(wfd_session_s *session)
427 __WDS_LOG_FUNC_ENTER__;
428 wfd_manager_s *manager = wfd_get_manager();
429 wfd_oem_conn_param_s param;
430 wfd_device_s *peer = NULL;
434 WDS_LOGE("Invalid parameter");
435 __WDS_LOG_FUNC_EXIT__;
439 if (session->state > SESSION_STATE_GO_NEG) {
440 WDS_LOGE("Session already finished GO Negotiation");
444 session->state = SESSION_STATE_GO_NEG;
445 peer = session->peer;
447 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
448 param.wps_mode = session->wps_mode;
449 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
450 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
451 param.go_intent = session->go_intent;
452 param.freq = session->freq;
453 if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
454 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
456 if (session->wps_pin[0] != '\0')
457 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
459 /* To connect with windows phone,set go_intent value to 2.
460 * As windows phone does not connect when local device act as GO.
461 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
462 * WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
463 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
465 if ((peer->pri_dev_type == 1) ||
466 ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
468 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
471 WDS_LOGD("connection go_intent: %d", param.go_intent);
472 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
474 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
475 wfd_destroy_session(manager);
476 __WDS_LOG_FUNC_EXIT__;
480 wfd_session_timer(session, 1);
482 __WDS_LOG_FUNC_EXIT__;
486 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
488 __WDS_LOG_FUNC_ENTER__;
489 wfd_manager_s *manager = wfd_get_manager();
492 if (!session || !session->peer) {
493 WDS_LOGE("Invalid parameter");
494 __WDS_LOG_FUNC_EXIT__;
495 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
498 if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
499 WDS_LOGE("Peer is not included in this session");
500 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
503 if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
504 res = wfd_oem_wps_cancel(manager->oem_ops);
506 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
509 WDS_LOGE("Failed to cancel connection");
510 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
513 wfd_destroy_session(manager);
515 __WDS_LOG_FUNC_EXIT__;
519 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
521 __WDS_LOG_FUNC_ENTER__;
522 wfd_manager_s *manager = wfd_get_manager();
523 wfd_device_s *peer = NULL;
526 if (!session || !manager) {
527 WDS_LOGE("Invalid parameter");
528 __WDS_LOG_FUNC_EXIT__;
532 /* Invite received case state is just created */
533 if (session->state < SESSION_STATE_CREATED ||
534 session->state >= SESSION_STATE_STOPPED) {
535 WDS_LOGE("Session state is Invalid [%d]", session->state);
536 __WDS_LOG_FUNC_EXIT__;
541 * TODO: check session status and do proper work
542 * for example, reject prov_disc, reject nego, stop wps, etc.
546 peer = session->peer;
548 if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
549 res = wfd_oem_wps_cancel(manager->oem_ops);
551 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
553 WDS_LOGE("Failed to reject connection");
554 __WDS_LOG_FUNC_EXIT__;
558 wfd_destroy_session(manager);
559 /* TODO: send notification to App */
561 __WDS_LOG_FUNC_EXIT__;
565 int wfd_session_join(wfd_session_s *session)
567 __WDS_LOG_FUNC_ENTER__;
568 wfd_manager_s *manager = wfd_get_manager();
569 wfd_oem_conn_param_s param;
570 wfd_device_s *peer = NULL;
574 WDS_LOGE("Invalid parameter");
575 __WDS_LOG_FUNC_EXIT__;
579 session->state = SESSION_STATE_WPS;
580 peer = session->peer;
582 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
583 param.wps_mode = session->wps_mode;
584 if (peer->dev_role == WFD_DEV_ROLE_GO)
585 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
586 param.go_intent = session->go_intent;
587 param.freq = session->freq;
588 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
590 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
592 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
593 wfd_destroy_session(manager);
594 __WDS_LOG_FUNC_EXIT__;
598 wfd_session_timer(session, 1);
600 __WDS_LOG_FUNC_EXIT__;
604 int wfd_session_invite(wfd_session_s *session)
606 __WDS_LOG_FUNC_ENTER__;
607 wfd_manager_s *manager = wfd_get_manager();
608 wfd_oem_invite_param_s param;
609 wfd_device_s *peer = NULL;
610 wfd_group_s *group = NULL;
614 WDS_LOGE("Invalid parameter");
615 __WDS_LOG_FUNC_EXIT__;
619 if (session->state > SESSION_STATE_CREATED) {
620 WDS_LOGE("Invalid session state(%d)", session->state);
624 peer = session->peer;
625 group = (wfd_group_s*) manager->group;
627 memset(¶m, 0x00, sizeof(wfd_oem_invite_param_s));
628 param.ifname = strdup(group->ifname);
629 memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
631 WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
632 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
634 res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, ¶m);
636 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
637 wfd_destroy_session(manager);
638 __WDS_LOG_FUNC_EXIT__;
642 wfd_session_timer(session, 1);
644 __WDS_LOG_FUNC_EXIT__;
648 int wfd_session_wps(wfd_session_s *session)
650 __WDS_LOG_FUNC_ENTER__;
651 wfd_manager_s *manager = wfd_get_manager();
652 wfd_device_s *peer = NULL;
656 WDS_LOGE("Invalid parameter");
657 __WDS_LOG_FUNC_EXIT__;
661 if (session->state > SESSION_STATE_WPS) {
662 WDS_LOGE("Session already starts WPS");
666 session->state = SESSION_STATE_WPS;
667 peer = session->peer;
669 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
670 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
671 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
673 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
674 wfd_oem_conn_param_s param;
675 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
676 param.wps_mode = session->wps_mode;
677 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
678 param.freq = session->freq; /* currently not used */
679 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
680 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
683 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
684 wfd_destroy_session(manager);
685 __WDS_LOG_FUNC_EXIT__;
689 __WDS_LOG_FUNC_EXIT__;
693 /* In case of incomming session, when user accept connection request, this function should be called.
694 * In case of outgoing session, when prov_disc response arrived, this function should be called.
695 * Even though peer is GO, we can use this function, which can decide using join itself.
697 int wfd_session_asp_connect(wfd_session_s *session, int role)
699 __WDS_LOG_FUNC_ENTER__;
700 wfd_manager_s *manager = wfd_get_manager();
701 wfd_oem_conn_param_s param;
702 wfd_device_s *peer = NULL;
706 WDS_LOGE("Invalid parameter");
707 __WDS_LOG_FUNC_EXIT__;
711 if (session->state >= SESSION_STATE_GO_NEG) {
712 WDS_LOGE("Session already starting GO Negotiation");
713 __WDS_LOG_FUNC_EXIT__;
717 if (role == WFD_OEM_ASP_SESSION_ROLE_GO) {
718 session->state = SESSION_STATE_WPS;
721 session->state = SESSION_STATE_GO_NEG;
724 peer = session->peer;
726 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
727 param.wps_mode = session->wps_mode;
729 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
730 param.go_intent = session->go_intent;
731 param.freq = session->freq;
732 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
734 if (session->wps_pin[0] != '\0')
735 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
737 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
739 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
740 wfd_destroy_session(manager);
741 __WDS_LOG_FUNC_EXIT__;
745 wfd_session_timer(session, 1);
747 __WDS_LOG_FUNC_EXIT__;
751 /* In case of incomming session, when user accept connection request, this function should be called.
752 * In case of outgoing session, when prov_disc response arrived, this function should be called.
753 * Even though peer is GO, we can use this function, which can decide using join itself.
755 int wfd_session_asp_persistent_connect(wfd_session_s *session, int persist_group_id)
757 __WDS_LOG_FUNC_ENTER__;
758 wfd_manager_s *manager = wfd_get_manager();
759 wfd_oem_group_param_s param;
763 WDS_LOGE("Invalid parameter");
764 __WDS_LOG_FUNC_EXIT__;
768 if (session->state > SESSION_STATE_GO_NEG) {
769 WDS_LOGE("Session already finished GO Negotiation");
770 __WDS_LOG_FUNC_EXIT__;
774 session->state = SESSION_STATE_WPS;
776 memset(¶m, 0x0, sizeof(param));
777 param.persistent = 2;
778 param.persistent_group_id = persist_group_id;
780 res = wfd_oem_create_group(manager->oem_ops, ¶m);
782 WDS_LOGD("Failed to create persistent group for ASP");
783 wfd_destroy_session(manager);
784 __WDS_LOG_FUNC_EXIT__;
788 wfd_session_timer(session, 1);
790 __WDS_LOG_FUNC_EXIT__;
794 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
796 __WDS_LOG_FUNC_ENTER__;
797 wfd_device_s *peer = NULL;
800 WDS_LOGE("Invalid parameter");
804 peer = session->peer;
806 __WDS_LOG_FUNC_EXIT__;
810 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
812 __WDS_LOG_FUNC_ENTER__;
813 wfd_device_s *peer = NULL;
815 if (!session || !session->peer) {
816 WDS_LOGE("Invalid parameter");
820 peer = session->peer;
822 __WDS_LOG_FUNC_EXIT__;
823 return peer->dev_addr;
827 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
829 __WDS_LOG_FUNC_ENTER__;
831 __WDS_LOG_FUNC_EXIT__;
835 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
837 __WDS_LOG_FUNC_ENTER__;
839 __WDS_LOG_FUNC_EXIT__;
843 int wfd_session_set_freq(wfd_session_s *session, int freq)
845 __WDS_LOG_FUNC_ENTER__;
847 __WDS_LOG_FUNC_EXIT__;
851 int wfd_session_get_state(wfd_session_s *session)
853 __WDS_LOG_FUNC_ENTER__;
855 __WDS_LOG_FUNC_EXIT__;
859 int wfd_session_set_state(wfd_session_s *session, int state)
861 __WDS_LOG_FUNC_ENTER__;
863 __WDS_LOG_FUNC_EXIT__;
868 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
870 __WDS_LOG_FUNC_ENTER__;
871 wfd_session_s *session = NULL;
874 if (!manager || !event) {
875 WDS_LOGE("Invalid parameter");
879 WDS_LOGD("event ID [%d]", event->event_id);
880 session = manager->session;
882 switch (event->event_id) {
883 case WFD_OEM_EVENT_PROV_DISC_REQ:
885 int req_wps_mode = WFD_WPS_MODE_NONE;
887 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
888 req_wps_mode = WFD_WPS_MODE_KEYPAD;
889 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
890 req_wps_mode = WFD_WPS_MODE_DISPLAY;
892 req_wps_mode = WFD_WPS_MODE_PBC;
894 /* Only peer initiated connection or invitation session can be allowed */
896 if (session->type != SESSION_TYPE_INVITE) {
897 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
898 MAC2SECSTR(event->dev_addr));
901 WDS_LOGD("=====> session already exist. (invitation session)");
902 if (session->state > SESSION_STATE_WPS) {
903 WDS_LOGE("Session already starts WPS");
907 session->req_wps_mode = req_wps_mode;
908 session->wps_mode = event->wps_mode;
910 session = wfd_create_session(manager, event->dev_addr,
911 req_wps_mode, SESSION_DIRECTION_INCOMING);
913 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
914 MAC2SECSTR(event->dev_addr));
920 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
921 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
923 session->state = SESSION_STATE_STARTED;
924 if (session->type == SESSION_TYPE_INVITE)
925 WDS_LOGD("Invitation session");
926 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
927 session->type = SESSION_TYPE_JOIN;
929 session->type = SESSION_TYPE_NORMAL;
931 wfd_session_timer(session, 1);
933 /* Update local device */
934 manager->local->wps_mode = event->wps_mode;
936 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
937 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
939 if (session->type == SESSION_TYPE_INVITE) {
940 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
941 if (session->wps_mode != WFD_WPS_MODE_PBC) {
942 char peer_mac_address[MACSTR_LEN+1] = {0, };
944 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
945 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
947 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
948 WFD_EVENT_CONNECTION_WPS_REQ,
950 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
951 /* We have to wait until user type PIN using Keypad */
955 res = wfd_session_wps(session);
957 _wfd_notify_session_failed(manager, event->dev_addr);
959 char peer_mac_address[MACSTR_LEN+1] = {0, };
961 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
962 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
964 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
965 WFD_EVENT_CONNECTION_REQ,
970 case WFD_OEM_EVENT_PROV_DISC_RESP:
972 if (!session) { /* TODO: check validity of Event */
973 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
974 MAC2SECSTR(event->dev_addr));
978 if (session->state > SESSION_STATE_STARTED) {
979 WDS_LOGE("Unexpected event. Session is already started");
983 if (session->type == SESSION_TYPE_INVITE) {
984 WDS_LOGE("Session type is invite, ignore provision discovery response");
989 session->wps_mode = event->wps_mode;
990 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
991 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
992 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
993 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
994 session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
996 session->req_wps_mode = WFD_WPS_MODE_PBC;
999 session->state = SESSION_STATE_STARTED;
1000 wfd_session_timer(session, 1);
1002 /* Update local device */
1003 manager->local->wps_mode = event->wps_mode;
1004 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
1006 if (session->wps_mode != WFD_WPS_MODE_PBC) {
1007 char peer_mac_address[MACSTR_LEN+1] = {0, };
1009 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1010 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1012 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1013 WFD_EVENT_CONNECTION_WPS_REQ,
1015 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
1016 /* We have to wait until user type PIN using Keypad */
1021 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
1022 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
1023 res = wfd_session_wps(session);
1024 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
1025 WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
1026 res = wfd_session_join(session);
1028 WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
1029 res = wfd_session_connect(session);
1033 _wfd_notify_session_failed(manager, event->dev_addr);
1036 case WFD_OEM_EVENT_GO_NEG_REQ:
1039 session = wfd_create_session(manager, event->dev_addr,
1040 event->wps_mode, SESSION_DIRECTION_INCOMING);
1042 WDS_LOGE("Failed to create session");
1043 __WDS_LOG_FUNC_EXIT__;
1047 session->type = SESSION_TYPE_NORMAL;
1048 session->state = SESSION_STATE_GO_NEG;
1049 wfd_session_timer(session, 1);
1050 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
1051 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
1053 char peer_mac_address[MACSTR_LEN+1] = {0, };
1054 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1055 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1057 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1058 WFD_EVENT_CONNECTION_REQ,
1061 /* Sometimes, Provision Discovery response is not received.
1062 * At this time, connection should be triggered by GO Negotiation request event */
1063 if (session->direction == SESSION_DIRECTION_OUTGOING) {
1064 if (session->wps_mode == WFD_WPS_MODE_KEYPAD && session->wps_pin[0] == '\0')
1066 res = wfd_session_connect(session);
1068 /* In autoconnection mode, MT should not send GO Nego Req
1069 before receiving the GO Nego Req from peer (MO). */
1070 if (manager->autoconnection == TRUE)
1071 res = wfd_session_connect(session);
1074 _wfd_notify_session_failed(manager, event->dev_addr);
1078 case WFD_OEM_EVENT_GO_NEG_DONE:
1081 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1082 MAC2SECSTR(event->dev_addr));
1085 manager->local->dev_role = event->dev_role;
1086 session->state = SESSION_STATE_WPS;
1090 case WFD_OEM_EVENT_WPS_DONE:
1093 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1094 MAC2SECSTR(event->dev_addr));
1097 session->state = SESSION_STATE_KEY_NEG;
1101 case WFD_OEM_EVENT_STA_CONNECTED:
1104 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1105 MAC2SECSTR(event->dev_addr));
1108 session->state = SESSION_STATE_COMPLETED;
1112 case WFD_OEM_EVENT_ASP_PROV_START:
1114 int req_wps_mode = WFD_WPS_MODE_NONE;
1116 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1117 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1118 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1119 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1121 req_wps_mode = WFD_WPS_MODE_P2PS;
1123 session = wfd_create_session(manager, event->dev_addr,
1124 req_wps_mode, SESSION_DIRECTION_INCOMING);
1126 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1127 MAC2SECSTR(event->dev_addr));
1131 /* Update session */
1132 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1133 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1135 session->state = SESSION_STATE_STARTED;
1136 wfd_session_timer(session, 1);
1139 case WFD_OEM_EVENT_ASP_PROV_DONE:
1141 int req_wps_mode = WFD_WPS_MODE_NONE;
1143 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1144 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1145 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1146 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1148 req_wps_mode = WFD_WPS_MODE_P2PS;
1150 session = (wfd_session_s*) manager->session;
1152 session = wfd_create_session(manager, event->dev_addr,
1153 req_wps_mode, SESSION_DIRECTION_INCOMING);
1155 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1156 MAC2SECSTR(event->dev_addr));
1159 session->state = SESSION_STATE_STARTED;
1160 wfd_session_timer(session, 1);
1167 __WDS_LOG_FUNC_EXIT__;