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__;//LCOV_EXCL_LINE
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");//LCOV_EXCL_LINE
63 session->connecting_120 = 0;
65 WDS_LOGD("Session timer expired");//LCOV_EXCL_LINE
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__;//LCOV_EXCL_LINE
113 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
115 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
116 char peer_mac_address[MACSTR_LEN+1] = {0, };
118 snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
119 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
121 g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_FAILED,
122 WFD_EVENT_CONNECTION_RSP,
127 wfd_session_s *session = manager->session;
128 if (wfd_asp_is_asp_session(session)) {
129 wfd_asp_connect_status(session->session_mac,
131 ASP_CONNECT_STATUS_GROUP_FORMATION_STARTED,
135 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
136 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
137 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
139 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
140 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
143 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
146 int wfd_session_timer(wfd_session_s *session, int start)
148 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
151 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
152 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
157 if (!session->connecting_120)
158 session->connecting_120 = 1;
160 if (session->timer > 0) {
161 WDS_LOGE("Session timer already started");//LCOV_EXCL_LINE
162 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
165 session->timer = g_timeout_add(120000,
166 (GSourceFunc) _session_timeout_cb,
168 WDS_LOGD("Session timer started");//LCOV_EXCL_LINE
170 session->connecting_120 = 0;
171 if (session->timer > 0) {
172 g_source_remove(session->timer);
174 WDS_LOGD("Session timer stoped");//LCOV_EXCL_LINE
178 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
182 /* Check the session instance which has same peer address,
183 * before using this function */
184 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
186 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
187 wfd_manager_s *manager = (wfd_manager_s*) data;
188 wfd_session_s *session = NULL;
189 wfd_device_s *peer = NULL;
191 if (!data || !peer_addr) {
192 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
193 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
197 WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
199 if (manager->session) {
200 WDS_LOGE("Session already exist");//LCOV_EXCL_LINE
204 session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
206 WDS_LOGE("Failed to allocate memory for session");//LCOV_EXCL_LINE
207 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
211 peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
213 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
215 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
218 peer->state = WFD_PEER_STATE_CONNECTING;
220 session->peer = peer;
221 session->req_wps_mode = wps_mode;
222 if (wps_mode == WFD_WPS_MODE_DISPLAY)
223 session->wps_mode = WFD_WPS_MODE_KEYPAD;
224 else if (wps_mode == WFD_WPS_MODE_KEYPAD)
225 session->wps_mode = WFD_WPS_MODE_DISPLAY;
226 else if (wps_mode == WFD_WPS_MODE_P2PS)
227 session->wps_mode = WFD_WPS_MODE_P2PS;
229 session->wps_mode = wps_mode;
230 session->direction = direction;
231 session->state = SESSION_STATE_CREATED;
233 manager->session = session;
234 manager->local->wps_mode = session->wps_mode;
236 if (peer->dev_role == WFD_DEV_ROLE_GO &&
237 manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
238 char *generated_pin = NULL;
239 session->wps_mode = WFD_WPS_MODE_DISPLAY;
240 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
242 if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
243 WDS_LOGE("Failed to generate pin");//LCOV_EXCL_LINE
245 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
249 #if defined(BUILD_GTESTS)
250 generated_pin = g_strndup("12345678", PINSTR_LEN + 1);
251 #endif /* BUILD_GTESTS */
252 g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
253 g_free(generated_pin);
256 if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
257 manager->local->dev_role = WFD_DEV_ROLE_GC;
259 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
263 int wfd_destroy_session(void *data)
265 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
266 wfd_manager_s *manager = (wfd_manager_s*) data;
267 wfd_session_s *session = NULL;
268 wfd_device_s *peer = NULL;
271 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
275 session = (wfd_session_s*) manager->session;
277 WDS_LOGE("Session not found");//LCOV_EXCL_LINE /* self prevent */
280 wfd_session_timer(session, 0);
281 peer = session->peer;
282 WDS_LOGD("peer :%p", peer);
285 if (session->state == SESSION_STATE_COMPLETED)
286 peer->state = WFD_PEER_STATE_CONNECTED;
288 peer->state = WFD_PEER_STATE_DISCOVERED;
290 WDS_LOGE("Peer not found");//LCOV_EXCL_LINE
294 manager->session = NULL;
295 manager->local->wps_mode = WFD_WPS_MODE_PBC;
296 manager->autoconnection = 0;
297 memset(manager->auto_pin, 0x0, PINSTR_LEN);
298 if (manager->local->dev_role == WFD_DEV_ROLE_GC)
299 manager->local->dev_role = WFD_DEV_ROLE_NONE;
301 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
305 int wfd_session_start(wfd_session_s *session)
307 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
308 wfd_manager_s *manager = wfd_get_manager();
309 wfd_device_s *peer = NULL;
314 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
315 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
319 if (session->state > SESSION_STATE_STARTED) {
320 WDS_LOGE("Invalid session state(%d)", session->state);
324 /* Check: Invitation Received in Incomming case ->
325 * send prov_disc join
327 * Check: User select peer to connect with in Outgoing case ->
328 * send prov_disc wps_mode */
330 wfd_oem_stop_scan(manager->oem_ops);
332 session->state = SESSION_STATE_STARTED;
333 peer = session->peer;
334 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
336 res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
337 session->req_wps_mode, join);
339 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
340 MAC2SECSTR(peer->dev_addr));
341 wfd_destroy_session(manager);
342 /* TODO: send notification to App */
343 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
347 wfd_session_timer(session, 1);
349 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
353 int wfd_session_asp_session_start(wfd_session_s *session, wfd_oem_asp_prov_s *params)
355 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
357 wfd_manager_s *manager = wfd_get_manager();
360 if (session == NULL || params == NULL) {
361 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
362 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
366 if (session->state > SESSION_STATE_STARTED) {
367 WDS_LOGE("Invalid session state(%d)", session->state);
368 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
372 res = wfd_oem_asp_prov_disc_req(manager->oem_ops, params);
374 WDS_LOGD("Failed to send ASP provision discovery request to peer");//LCOV_EXCL_LINE
375 wfd_destroy_session(manager);
376 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
380 session->state = SESSION_STATE_STARTED;
381 session->session_id = params->session_id;
382 memcpy(session->session_mac, params->session_mac, MACADDR_LEN);
383 memcpy(session->service_mac, params->service_mac, MACADDR_LEN);
384 wfd_session_timer(session, 1);
386 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
391 int wfd_session_stop(wfd_session_s *session)
393 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
394 wfd_manager_s *manager = wfd_get_manager();
395 wfd_device_s *peer = NULL;
399 WDS_LOGE("Invalid parameter");
400 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
404 if (session->state > SESSION_STATE_CREATED) {
405 peer = session->peer;
406 if (session->direction == SESSION_DIRECTION_INCOMING)
407 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
408 else if (session->direction == SESSION_DIRECTION_OUTGOING)
409 res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
412 WDS_LOGE("Failed to reject or cancel connection");
413 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
418 session->state = SESSION_STATE_STOPPED;
419 wfd_destroy_session(manager);
421 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
426 /* In case of incomming session, when user accept connection request, this function should be called.
427 * In case of outgoing session, when prov_disc response arrived, this function should be called.
428 * Even though peer is GO, we can use this function, which can decide using join itself.
430 int wfd_session_connect(wfd_session_s *session)
432 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
433 wfd_manager_s *manager = wfd_get_manager();
434 wfd_oem_conn_param_s param;
435 wfd_device_s *peer = NULL;
439 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
440 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
444 if (session->state > SESSION_STATE_GO_NEG) {
445 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
449 session->state = SESSION_STATE_GO_NEG;
450 peer = session->peer;
452 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
453 param.wps_mode = session->wps_mode;
454 if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
455 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
456 param.go_intent = session->go_intent;
457 if (peer->display.availability)
458 param.go_intent = manager->go_intent_per_type[manager->local->display.type];
459 param.freq = session->freq;
460 if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
461 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
463 if (session->wps_pin[0] != '\0')
464 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
466 /* To connect with windows phone,set go_intent value to 2.
467 * As windows phone does not connect when local device act as GO.
468 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
469 * WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
470 * WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
472 if ((peer->pri_dev_type == 1) ||
473 ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
475 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
478 WDS_LOGD("connection go_intent: %d", param.go_intent);
479 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
481 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
482 wfd_destroy_session(manager);
483 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
487 wfd_session_timer(session, 1);
489 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
493 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
495 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
496 wfd_manager_s *manager = wfd_get_manager();
499 if (!session || !session->peer) {
500 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
501 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
502 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
505 if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
506 WDS_LOGE("Peer is not included in this session");//LCOV_EXCL_LINE
507 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
510 if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
511 res = wfd_oem_wps_cancel(manager->oem_ops);
513 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
516 WDS_LOGE("Failed to cancel connection");//LCOV_EXCL_LINE
517 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
520 wfd_destroy_session(manager);
522 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
526 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
528 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
529 wfd_manager_s *manager = wfd_get_manager();
530 wfd_device_s *peer = NULL;
533 if (!session || !manager) {
534 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
535 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
539 /* Invite received case state is just created */
540 if (session->state < SESSION_STATE_CREATED ||
541 session->state >= SESSION_STATE_STOPPED) {
542 WDS_LOGE("Session state is Invalid [%d]", session->state);
543 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
548 * TODO: check session status and do proper work
549 * for example, reject prov_disc, reject nego, stop wps, etc.
553 peer = session->peer;
555 if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
556 res = wfd_oem_wps_cancel(manager->oem_ops);
558 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
560 WDS_LOGE("Failed to reject connection");//LCOV_EXCL_LINE
561 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
565 wfd_destroy_session(manager);
566 /* TODO: send notification to App */
568 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
572 int wfd_session_join(wfd_session_s *session)
574 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
575 wfd_manager_s *manager = wfd_get_manager();
576 wfd_oem_conn_param_s param;
577 wfd_device_s *peer = NULL;
581 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
582 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
586 session->state = SESSION_STATE_WPS;
587 peer = session->peer;
589 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
590 param.wps_mode = session->wps_mode;
591 if (peer->dev_role == WFD_DEV_ROLE_GO)
592 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
593 param.go_intent = session->go_intent;
594 param.freq = session->freq;
595 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
597 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
599 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
600 wfd_destroy_session(manager);
601 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
605 wfd_session_timer(session, 1);
607 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
611 int wfd_session_invite(wfd_session_s *session)
613 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
614 wfd_manager_s *manager = wfd_get_manager();
615 wfd_oem_invite_param_s param;
616 wfd_device_s *peer = NULL;
617 wfd_group_s *group = NULL;
621 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
622 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
626 if (session->state > SESSION_STATE_CREATED) {
627 WDS_LOGE("Invalid session state(%d)", session->state);
631 peer = session->peer;
632 group = (wfd_group_s*) manager->group;
634 memset(¶m, 0x00, sizeof(wfd_oem_invite_param_s));
635 param.ifname = g_strdup(group->ifname);
636 memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
638 WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
639 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
641 res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, ¶m);
643 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
644 wfd_destroy_session(manager);
645 g_free(param.ifname);
646 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
650 wfd_session_timer(session, 1);
651 g_free(param.ifname);
653 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
657 int wfd_session_wps(wfd_session_s *session)
659 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
660 wfd_manager_s *manager = wfd_get_manager();
661 wfd_device_s *peer = NULL;
665 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
666 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
670 if (session->state > SESSION_STATE_WPS) {
671 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
675 session->state = SESSION_STATE_WPS;
676 peer = session->peer;
678 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
679 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
680 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
682 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
683 wfd_oem_conn_param_s param;
684 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
685 param.wps_mode = session->wps_mode;
686 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
687 param.freq = session->freq; /* currently not used */
688 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
689 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
692 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
693 wfd_destroy_session(manager);
694 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
698 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
702 /* In case of incomming session, when user accept connection request, this function should be called.
703 * In case of outgoing session, when prov_disc response arrived, this function should be called.
704 * Even though peer is GO, we can use this function, which can decide using join itself.
706 int wfd_session_asp_connect(wfd_session_s *session, int role)
708 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
709 wfd_manager_s *manager = wfd_get_manager();
710 wfd_oem_conn_param_s param;
711 wfd_device_s *peer = NULL;
715 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
716 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
720 if (session->state >= SESSION_STATE_GO_NEG) {
721 WDS_LOGE("Session already starting GO Negotiation");//LCOV_EXCL_LINE
722 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
726 if (role == WFD_OEM_ASP_SESSION_ROLE_GO) {
727 session->state = SESSION_STATE_WPS;
730 session->state = SESSION_STATE_GO_NEG;
733 peer = session->peer;
735 memset(¶m, 0x00, sizeof(wfd_oem_conn_param_s));
736 param.wps_mode = session->wps_mode;
738 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
739 param.go_intent = session->go_intent;
740 param.freq = session->freq;
741 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
743 if (session->wps_pin[0] != '\0')
744 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
746 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, ¶m);
748 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
749 wfd_destroy_session(manager);
750 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
754 wfd_session_timer(session, 1);
756 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
760 /* In case of incomming session, when user accept connection request, this function should be called.
761 * In case of outgoing session, when prov_disc response arrived, this function should be called.
762 * Even though peer is GO, we can use this function, which can decide using join itself.
764 int wfd_session_asp_persistent_connect(wfd_session_s *session, int persist_group_id)
766 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
767 wfd_manager_s *manager = wfd_get_manager();
768 wfd_oem_group_param_s param;
772 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
773 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
777 if (session->state > SESSION_STATE_GO_NEG) {
778 WDS_LOGE("Session already finished GO Negotiation");//LCOV_EXCL_LINE
779 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
783 session->state = SESSION_STATE_WPS;
785 memset(¶m, 0x0, sizeof(param));
786 param.persistent = 2;
787 param.persistent_group_id = persist_group_id;
789 res = wfd_oem_create_group(manager->oem_ops, ¶m);
791 WDS_LOGD("Failed to create persistent group for ASP");//LCOV_EXCL_LINE
792 wfd_destroy_session(manager);
793 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
797 wfd_session_timer(session, 1);
799 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
803 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
805 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
806 wfd_device_s *peer = NULL;
809 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
813 peer = session->peer;
815 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
819 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
821 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
822 wfd_device_s *peer = NULL;
824 if (!session || !session->peer) {
825 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
829 peer = session->peer;
831 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
832 return peer->dev_addr;
836 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
838 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
840 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
844 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
846 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
848 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
852 int wfd_session_set_freq(wfd_session_s *session, int freq)
854 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
856 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
860 int wfd_session_get_state(wfd_session_s *session)
862 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
864 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
868 int wfd_session_set_state(wfd_session_s *session, int state)
870 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
872 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
877 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
879 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
880 wfd_session_s *session = NULL;
883 if (!manager || !event) {
884 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
888 WDS_LOGD("event ID [%d]", event->event_id);
889 session = manager->session;
891 switch (event->event_id) {
892 case WFD_OEM_EVENT_PROV_DISC_REQ:
894 int req_wps_mode = WFD_WPS_MODE_NONE;
896 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
897 req_wps_mode = WFD_WPS_MODE_KEYPAD;
898 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
899 req_wps_mode = WFD_WPS_MODE_DISPLAY;
901 req_wps_mode = WFD_WPS_MODE_PBC;
903 /* Only peer initiated connection or invitation session can be allowed */
905 if (session->type != SESSION_TYPE_INVITE) {
906 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
907 MAC2SECSTR(event->dev_addr));
910 WDS_LOGD("=====> session already exist. (invitation session)");//LCOV_EXCL_LINE
911 if (session->state > SESSION_STATE_WPS) {
912 WDS_LOGE("Session already starts WPS");//LCOV_EXCL_LINE
916 session->req_wps_mode = req_wps_mode;
917 session->wps_mode = event->wps_mode;
919 session = wfd_create_session(manager, event->dev_addr,
920 req_wps_mode, SESSION_DIRECTION_INCOMING);
922 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
923 MAC2SECSTR(event->dev_addr));
929 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
930 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
932 session->state = SESSION_STATE_STARTED;
933 if (session->type == SESSION_TYPE_INVITE)
934 WDS_LOGD("Invitation session");//LCOV_EXCL_LINE
935 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
936 session->type = SESSION_TYPE_JOIN;
938 session->type = SESSION_TYPE_NORMAL;
940 wfd_session_timer(session, 1);
942 /* Update local device */
943 manager->local->wps_mode = event->wps_mode;
945 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
946 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
948 if (session->type == SESSION_TYPE_INVITE) {
949 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
950 if (session->wps_mode != WFD_WPS_MODE_PBC) {
951 char peer_mac_address[MACSTR_LEN+1] = {0, };
953 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
954 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
956 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
957 WFD_EVENT_CONNECTION_WPS_REQ,
959 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
960 /* We have to wait until user type PIN using Keypad */
964 res = wfd_session_wps(session);
966 _wfd_notify_session_failed(manager, event->dev_addr);
968 char peer_mac_address[MACSTR_LEN+1] = {0, };
970 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
971 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
973 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
974 WFD_EVENT_CONNECTION_REQ,
979 case WFD_OEM_EVENT_PROV_DISC_RESP:
981 if (!session) { /* TODO: check validity of Event */
982 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
983 MAC2SECSTR(event->dev_addr));
987 if (session->state > SESSION_STATE_STARTED) {
988 WDS_LOGE("Unexpected event. Session is already started");//LCOV_EXCL_LINE
992 if (session->type == SESSION_TYPE_INVITE) {
993 WDS_LOGE("Session type is invite, ignore provision discovery response");//LCOV_EXCL_LINE
998 session->wps_mode = event->wps_mode;
999 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
1000 session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
1001 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1002 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
1003 session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
1005 session->req_wps_mode = WFD_WPS_MODE_PBC;
1008 session->state = SESSION_STATE_STARTED;
1009 wfd_session_timer(session, 1);
1011 /* Update local device */
1012 manager->local->wps_mode = event->wps_mode;
1013 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
1015 if (session->wps_mode != WFD_WPS_MODE_PBC) {
1016 char peer_mac_address[MACSTR_LEN+1] = {0, };
1018 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1019 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1021 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1022 WFD_EVENT_CONNECTION_WPS_REQ,
1024 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
1025 /* We have to wait until user type PIN using Keypad */
1030 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
1031 WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
1032 res = wfd_session_wps(session);
1033 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
1034 WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
1035 res = wfd_session_join(session);
1037 WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
1038 res = wfd_session_connect(session);
1042 _wfd_notify_session_failed(manager, event->dev_addr);
1045 case WFD_OEM_EVENT_GO_NEG_REQ:
1048 session = wfd_create_session(manager, event->dev_addr,
1049 event->wps_mode, SESSION_DIRECTION_INCOMING);
1051 WDS_LOGE("Failed to create session");//LCOV_EXCL_LINE
1052 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
1056 session->type = SESSION_TYPE_NORMAL;
1057 session->state = SESSION_STATE_GO_NEG;
1058 wfd_session_timer(session, 1);
1059 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
1060 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTING);
1062 if (manager->autoconnection == TRUE) {
1064 * TODO: Add autoconnection peer matching logic.
1067 * In autoconnection mode, connection request notification
1068 * should not be sent to library.
1070 res = wfd_session_connect(session);
1072 char peer_mac_address[MACSTR_LEN+1] = {0, };
1073 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
1074 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
1076 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
1077 WFD_EVENT_CONNECTION_REQ,
1081 /* Sometimes, Provision Discovery response is not received.
1082 * At this time, connection should be triggered by GO Negotiation request event */
1083 if (session->direction == SESSION_DIRECTION_OUTGOING) {
1084 if (session->wps_mode == WFD_WPS_MODE_KEYPAD && session->wps_pin[0] == '\0')
1086 res = wfd_session_connect(session);
1089 * TODO: Add autoconnection peer matching logic.
1092 * In autoconnection mode, MT should not send GO Nego Req
1093 * before receiving the GO Nego Req from peer (MO).
1095 if (manager->autoconnection == TRUE)
1096 res = wfd_session_connect(session);
1099 _wfd_notify_session_failed(manager, event->dev_addr);
1103 case WFD_OEM_EVENT_GO_NEG_DONE:
1106 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1107 MAC2SECSTR(event->dev_addr));
1110 manager->local->dev_role = event->dev_role;
1111 session->state = SESSION_STATE_WPS;
1115 case WFD_OEM_EVENT_WPS_DONE:
1118 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1119 MAC2SECSTR(event->dev_addr));
1122 session->state = SESSION_STATE_KEY_NEG;
1126 case WFD_OEM_EVENT_STA_CONNECTED:
1129 WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
1130 MAC2SECSTR(event->dev_addr));
1133 session->state = SESSION_STATE_COMPLETED;
1137 case WFD_OEM_EVENT_ASP_PROV_START:
1139 int req_wps_mode = WFD_WPS_MODE_NONE;
1141 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1142 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1143 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1144 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1146 req_wps_mode = WFD_WPS_MODE_P2PS;
1148 session = wfd_create_session(manager, event->dev_addr,
1149 req_wps_mode, SESSION_DIRECTION_INCOMING);
1151 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1152 MAC2SECSTR(event->dev_addr));
1156 /* Update session */
1157 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1158 g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
1160 session->state = SESSION_STATE_STARTED;
1161 wfd_session_timer(session, 1);
1164 case WFD_OEM_EVENT_ASP_PROV_DONE:
1166 int req_wps_mode = WFD_WPS_MODE_NONE;
1168 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
1169 req_wps_mode = WFD_WPS_MODE_KEYPAD;
1170 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
1171 req_wps_mode = WFD_WPS_MODE_DISPLAY;
1173 req_wps_mode = WFD_WPS_MODE_P2PS;
1175 session = (wfd_session_s*) manager->session;
1177 session = wfd_create_session(manager, event->dev_addr,
1178 req_wps_mode, SESSION_DIRECTION_INCOMING);
1180 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
1181 MAC2SECSTR(event->dev_addr));
1184 session->state = SESSION_STATE_STARTED;
1185 wfd_session_timer(session, 1);
1192 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE