Changed File permissions 755 => 644.
[platform/core/connectivity/wifi-direct-manager.git] / src / wifi-direct-session.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 /**
21  * This file implements wifi direct session functions.
22  *
23  * @file                wifi-direct-session.c
24  * @author      Gibyoung Kim (lastkgb.kim@samsung.com)
25  * @version     0.7
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include <glib.h>
32
33 #include <wifi-direct.h>
34
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
48
49 static gboolean _session_timeout_cb(gpointer *user_data)
50 {
51         __WDS_LOG_FUNC_ENTER__;
52         wfd_manager_s *manager = wfd_get_manager();
53         wfd_session_s *session = (wfd_session_s*) manager->session;
54         unsigned char *peer_addr = NULL;
55         char peer_mac_address[MACSTR_LEN+1] = {0, };
56
57         if (!session) {
58                 WDS_LOGE("Invalid parameter");
59                 return FALSE;
60         }
61         session->connecting_120 = 0;
62         session->timer = 0;
63         WDS_LOGD("Session timer expired");
64
65         peer_addr = wfd_session_get_peer_addr(session);
66         if (peer_addr != NULL)
67                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
68         else
69                 g_snprintf(peer_mac_address, MACSTR_LEN, "%s", "");
70
71         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
72                                      "Connection",
73                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT,
74                                                             WFD_EVENT_CONNECTION_RSP,
75                                                             peer_mac_address));
76
77         wfd_session_cancel(session, peer_addr);
78
79         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
80
81                 wfd_group_s *group = (wfd_group_s*) manager->group;
82                 if (group && wfd_util_is_remove_group_allowed()) {
83                         wfd_oem_destroy_group(manager->oem_ops, group->ifname);
84                 } else {
85                         wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
86                         wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
87                 }
88         } else {
89                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
90                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
91         }
92
93         __WDS_LOG_FUNC_EXIT__;
94         return FALSE;
95 }
96
97 static void _wfd_notify_session_failed(wfd_manager_s *manager, unsigned char *peer_addr)
98 {
99         __WDS_LOG_FUNC_ENTER__;
100         char peer_mac_address[MACSTR_LEN+1] = {0, };
101
102         snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer_addr));
103         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
104                                      "Connection",
105                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_CONNECTION_FAILED,
106                                                             WFD_EVENT_CONNECTION_RSP,
107                                                             peer_mac_address));
108
109         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
110                 wfd_state_set(manager, WIFI_DIRECT_STATE_GROUP_OWNER);
111                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_GROUP_OWNER);
112         } else {
113                 wfd_state_set(manager, WIFI_DIRECT_STATE_ACTIVATED);
114                 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_ACTIVATED);
115         }
116
117         __WDS_LOG_FUNC_EXIT__;
118 }
119
120 int wfd_session_timer(wfd_session_s *session, int start)
121 {
122         __WDS_LOG_FUNC_ENTER__;
123
124         if (!session) {
125                 WDS_LOGE("Invalid parameter");
126                 __WDS_LOG_FUNC_EXIT__;
127                 return -1;
128         }
129
130         if (start) {
131                 if (!session->connecting_120)
132                         session->connecting_120 = 1;
133
134                 if (session->timer > 0) {
135                         WDS_LOGE("Session timer already started");
136                         __WDS_LOG_FUNC_EXIT__;
137                         return -1;
138                 }
139                 session->timer = g_timeout_add(120000,
140                                                 (GSourceFunc) _session_timeout_cb,
141                                                 NULL);
142                 WDS_LOGD("Session timer started");
143         } else {
144                 session->connecting_120 = 0;
145                 if (session->timer > 0) {
146                         g_source_remove(session->timer);
147                         session->timer = 0;
148                         WDS_LOGD("Session timer stoped");
149                 }
150         }
151
152         __WDS_LOG_FUNC_EXIT__;
153         return 0;
154 }
155
156 /* Check the session instance which has same peer address,
157  * before using this function */
158 wfd_session_s *wfd_create_session(void *data, unsigned char *peer_addr, int wps_mode, int direction)
159 {
160         __WDS_LOG_FUNC_ENTER__;
161         wfd_manager_s *manager = (wfd_manager_s*) data;
162         wfd_session_s *session = NULL;
163         wfd_device_s *peer = NULL;
164
165         if (!data || !peer_addr) {
166                 WDS_LOGE("Invalid parameter");
167                 __WDS_LOG_FUNC_EXIT__;
168                 return NULL;
169         }
170
171         WDS_LOGD("create session for peer[" MACSTR "]", MAC2STR(peer_addr));
172
173         if (manager->session) {
174                 WDS_LOGE("Session already exist");
175                 return NULL;
176         }
177
178         session = (wfd_session_s*) g_try_malloc0(sizeof(wfd_session_s));
179         if (!session) {
180                 WDS_LOGE("Failed to allocate memory for session");
181                 __WDS_LOG_FUNC_EXIT__;
182                 return NULL;
183         }
184
185         peer = wfd_peer_find_by_dev_addr(manager, peer_addr);
186         if (!peer) {
187                 WDS_LOGE("Failed to find peer info[" MACSECSTR "]", MAC2SECSTR(peer_addr));
188                 g_free(session);
189                 __WDS_LOG_FUNC_EXIT__;
190                 return NULL;
191         }
192         peer->state = WFD_PEER_STATE_CONNECTING;
193
194         session->peer = peer;
195         session->req_wps_mode = wps_mode;
196         if (wps_mode == WFD_WPS_MODE_DISPLAY)
197                 session->wps_mode = WFD_WPS_MODE_KEYPAD;
198         else if (wps_mode == WFD_WPS_MODE_KEYPAD)
199                 session->wps_mode = WFD_WPS_MODE_DISPLAY;
200         else
201                 session->wps_mode = wps_mode;
202         session->direction = direction;
203         session->state = SESSION_STATE_CREATED;
204
205         manager->session = session;
206         manager->local->wps_mode = session->wps_mode;
207
208         if (peer->dev_role == WFD_DEV_ROLE_GO &&
209                         manager->local->wps_mode == WFD_WPS_MODE_DISPLAY) {
210                         char *generated_pin = NULL;
211                         session->wps_mode = WFD_WPS_MODE_DISPLAY;
212                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
213
214                         if (wfd_oem_generate_pin(manager->oem_ops, &generated_pin) != 0) {
215                                 WDS_LOGE("Failed to generate pin");
216                                 g_free(session);
217                                 __WDS_LOG_FUNC_EXIT__;
218                                 return NULL;
219                         }
220
221                         g_strlcpy(session->wps_pin, generated_pin, PINSTR_LEN + 1);
222                         g_free(generated_pin);
223         }
224
225         if (peer->dev_role == WFD_DEV_ROLE_GO && manager->local->dev_role != WFD_DEV_ROLE_GO)
226                 manager->local->dev_role = WFD_DEV_ROLE_GC;
227
228         __WDS_LOG_FUNC_EXIT__;
229         return session;
230 }
231
232 int wfd_destroy_session(void *data)
233 {
234         __WDS_LOG_FUNC_ENTER__;
235         wfd_manager_s *manager = (wfd_manager_s*) data;
236         wfd_session_s *session = NULL;
237         wfd_device_s *peer = NULL;
238
239         if (!manager) {
240                 WDS_LOGE("Invalid parameter");
241                 return -1;
242         }
243
244         session = (wfd_session_s*) manager->session;
245         if (!session) {
246                 WDS_LOGE("Session not found");  /* self prevent */
247                 return -1;
248         }
249         wfd_session_timer(session, 0);
250         peer = session->peer;
251
252         if (peer) {
253                 if (session->state == SESSION_STATE_COMPLETED)
254                         peer->state = WFD_PEER_STATE_CONNECTED;
255                 else
256                         peer->state = WFD_PEER_STATE_DISCOVERED;
257         } else {
258                 WDS_LOGE("Peer not found");
259         }
260
261         g_free(session);
262         manager->session = NULL;
263         manager->local->wps_mode = WFD_WPS_MODE_PBC;
264         manager->autoconnection = 0;
265         memset(manager->auto_pin, 0x0, PINSTR_LEN);
266         if (manager->local->dev_role == WFD_DEV_ROLE_GC)
267                 manager->local->dev_role = WFD_DEV_ROLE_NONE;
268
269         __WDS_LOG_FUNC_EXIT__;
270         return 0;
271 }
272
273 int wfd_session_start(wfd_session_s *session)
274 {
275         __WDS_LOG_FUNC_ENTER__;
276         wfd_manager_s *manager = wfd_get_manager();
277         wfd_device_s *peer = NULL;
278         int join = 0;
279         int res = 0;
280
281         if (!session) {
282                 WDS_LOGE("Invalid parameter");
283                 __WDS_LOG_FUNC_EXIT__;
284                 return -1;
285         }
286
287         if (session->state > SESSION_STATE_STARTED) {
288                 WDS_LOGE("Invalid session state(%d)", session->state);
289                 return -1;
290         }
291
292         /* Check: Invitation Received in Incomming case ->
293          * send prov_disc join
294          *
295          * Check: User select peer to connect with in Outgoing case ->
296          * send prov_disc wps_mode */
297
298         wfd_oem_stop_scan(manager->oem_ops);
299
300         session->state = SESSION_STATE_STARTED;
301         peer = session->peer;
302         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
303                 join = 1;
304         res = wfd_oem_prov_disc_req(manager->oem_ops, peer->dev_addr,
305                                         session->req_wps_mode, join);
306         if (res < 0) {
307                 WDS_LOGD("Failed to send provision discovery request to peer [" MACSECSTR "]",
308                                                                         MAC2SECSTR(peer->dev_addr));
309                 wfd_destroy_session(manager);
310                 /* TODO: send notification to App */
311                 __WDS_LOG_FUNC_EXIT__;
312                 return -1;
313         }
314
315         wfd_session_timer(session, 1);
316
317         __WDS_LOG_FUNC_EXIT__;
318         return 0;
319 }
320
321 #if 0
322 int wfd_session_stop(wfd_session_s *session)
323 {
324         __WDS_LOG_FUNC_ENTER__;
325         wfd_manager_s *manager = wfd_get_manager();
326         wfd_device_s *peer = NULL;
327         int res = 0;
328
329         if (!session) {
330                 WDS_LOGE("Invalid parameter");
331                 __WDS_LOG_FUNC_EXIT__;
332                 return -1;
333         }
334
335         if (session->state > SESSION_STATE_CREATED) {
336                 peer = session->peer;
337                 if (session->direction == SESSION_DIRECTION_INCOMING)
338                         res  = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
339                 else if (session->direction == SESSION_DIRECTION_OUTGOING)
340                         res = wfd_oem_cancel_connection(manager->oem_ops, peer->dev_addr);
341
342                         if (res < 0) {
343                         WDS_LOGE("Failed to reject or cancel connection");
344                         __WDS_LOG_FUNC_EXIT__;
345                         return -1;
346                 }
347         }
348
349         session->state = SESSION_STATE_STOPPED;
350         wfd_destroy_session(manager);
351
352         __WDS_LOG_FUNC_EXIT__;
353         return 0;
354 }
355 #endif
356
357 /* In case of incomming session, when user accept connection request, this function should be called.
358  * In case of outgoing session, when prov_disc response arrived, this function should be called.
359  * Even though peer is GO, we can use this function, which can decide using join itself.
360  */
361 int wfd_session_connect(wfd_session_s *session)
362 {
363         __WDS_LOG_FUNC_ENTER__;
364         wfd_manager_s *manager = wfd_get_manager();
365         wfd_oem_conn_param_s param;
366         wfd_device_s *peer = NULL;
367         int res = 0;
368
369         if (!session) {
370                 WDS_LOGE("Invalid parameter");
371                 __WDS_LOG_FUNC_EXIT__;
372                 return -1;
373         }
374
375         if (session->state > SESSION_STATE_GO_NEG) {
376                 WDS_LOGE("Session already finished GO Negotiation");
377                 return -1;
378         }
379
380         session->state = SESSION_STATE_GO_NEG;
381         peer = session->peer;
382
383         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
384         param.wps_mode = session->wps_mode;
385         if (peer->dev_role == WFD_DEV_ROLE_GO || session->type == SESSION_TYPE_INVITE)
386                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
387         param.go_intent = session->go_intent;
388         param.freq = session->freq;
389         if (manager->local->group_flags & WFD_GROUP_FLAG_PERSISTENT)
390                 param.conn_flags |= WFD_OEM_CONN_TYPE_PERSISTENT;
391
392         if (session->wps_pin[0] != '\0')
393                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
394
395         /* To connect with windows phone,set go_intent value to 2.
396         *  As windows phone does not connect when local device act as GO.
397         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_COMPUTER ==>1 (Assume Peer Device is Windows PC)
398         *  WIFI_DIRECT_SECONDARY_DEVICE_TYPE_TELEPHONE_WINDOWS_MOBILE ==>1
399         *  WIFI_DIRECT_PRIMARY_DEVICE_TYPE_TELEPHONE ==> 10
400         */
401          if ((peer->pri_dev_type == 1) ||
402                                  ((peer->pri_dev_type == 10) && (peer->sec_dev_type == 1))) {
403                 param.go_intent = 2;
404                 WDS_LOGD("go_intent set to %d, Windows device", param.go_intent);
405          }
406
407         WDS_LOGD("connection go_intent: %d", param.go_intent);
408         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
409         if (res < 0) {
410                 WDS_LOGD("Failed to connect peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
411                 wfd_destroy_session(manager);
412                 __WDS_LOG_FUNC_EXIT__;
413                 return -1;
414         }
415
416         wfd_session_timer(session, 1);
417
418         __WDS_LOG_FUNC_EXIT__;
419         return 0;
420 }
421
422 int wfd_session_cancel(wfd_session_s *session, unsigned char *peer_addr)
423 {
424         __WDS_LOG_FUNC_ENTER__;
425         wfd_manager_s *manager = wfd_get_manager();
426         int res = 0;
427
428         if (!session || !session->peer) {
429                 WDS_LOGE("Invalid parameter");
430                 __WDS_LOG_FUNC_EXIT__;
431                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
432         }
433
434         if (memcmp(peer_addr, session->peer->dev_addr, MACADDR_LEN)) {
435                 WDS_LOGE("Peer is not included in this session");
436                 return WIFI_DIRECT_ERROR_NOT_PERMITTED;
437         }
438
439         if (manager->local->dev_role == WFD_DEV_ROLE_GO && session->state > SESSION_STATE_GO_NEG)
440                 res = wfd_oem_wps_cancel(manager->oem_ops);
441         else
442                 res = wfd_oem_cancel_connection(manager->oem_ops, peer_addr);
443
444         if (res < 0) {
445                 WDS_LOGE("Failed to cancel connection");
446                 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
447         }
448
449         wfd_destroy_session(manager);
450
451         __WDS_LOG_FUNC_EXIT__;
452         return 0;
453 }
454
455 int wfd_session_reject(wfd_session_s *session, unsigned char *peer_addr)
456 {
457         __WDS_LOG_FUNC_ENTER__;
458         wfd_manager_s *manager = wfd_get_manager();
459         wfd_device_s *peer = NULL;
460         int res = 0;
461
462         if (!session || !manager) {
463                 WDS_LOGE("Invalid parameter");
464                 __WDS_LOG_FUNC_EXIT__;
465                 return -1;
466         }
467
468         /* Invite received case state is just created */
469         if (session->state < SESSION_STATE_CREATED ||
470                 session->state >= SESSION_STATE_STOPPED) {
471                 WDS_LOGE("Session state is Invalid [%d]", session->state);
472                 __WDS_LOG_FUNC_EXIT__;
473                 return -1;
474         }
475
476         /*
477          * TODO: check session status and do proper work
478          * for example, reject prov_disc, reject nego, stop wps, etc.
479          *
480          */
481
482         peer = session->peer;
483
484         if (SESSION_TYPE_INVITE == session->type || SESSION_TYPE_JOIN == session->type)
485                 res = wfd_oem_wps_cancel(manager->oem_ops);
486         else
487                 res = wfd_oem_reject_connection(manager->oem_ops, peer->dev_addr);
488         if (res < 0) {
489                 WDS_LOGE("Failed to reject connection");
490                 __WDS_LOG_FUNC_EXIT__;
491                 return -1;
492         }
493
494         wfd_destroy_session(manager);
495         /* TODO: send notification to App */
496
497         __WDS_LOG_FUNC_EXIT__;
498         return 0;
499 }
500
501 int wfd_session_join(wfd_session_s *session)
502 {
503         __WDS_LOG_FUNC_ENTER__;
504         wfd_manager_s *manager = wfd_get_manager();
505         wfd_oem_conn_param_s param;
506         wfd_device_s *peer = NULL;
507         int res = 0;
508
509         if (!session) {
510                 WDS_LOGE("Invalid parameter");
511                 __WDS_LOG_FUNC_EXIT__;
512                 return -1;
513         }
514
515         session->state = SESSION_STATE_WPS;
516         peer = session->peer;
517
518         memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
519         param.wps_mode = session->wps_mode;
520         if (peer->dev_role == WFD_DEV_ROLE_GO)
521                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
522         param.go_intent = session->go_intent;
523         param.freq = session->freq;
524         g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
525
526         res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
527         if (res < 0) {
528                 WDS_LOGD("Failed to join with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
529                 wfd_destroy_session(manager);
530                 __WDS_LOG_FUNC_EXIT__;
531                 return -1;
532         }
533
534         wfd_session_timer(session, 1);
535
536         __WDS_LOG_FUNC_EXIT__;
537         return 0;
538 }
539
540 int wfd_session_invite(wfd_session_s *session)
541 {
542         __WDS_LOG_FUNC_ENTER__;
543         wfd_manager_s *manager = wfd_get_manager();
544         wfd_oem_invite_param_s param;
545         wfd_device_s *peer = NULL;
546         wfd_group_s *group = NULL;
547         int res = 0;
548
549         if (!session) {
550                 WDS_LOGE("Invalid parameter");
551                 __WDS_LOG_FUNC_EXIT__;
552                 return -1;
553         }
554
555         if (session->state > SESSION_STATE_CREATED) {
556                 WDS_LOGE("Invalid session state(%d)", session->state);
557                 return -1;
558         }
559
560         peer = session->peer;
561         group = (wfd_group_s*) manager->group;
562
563         memset(&param, 0x00, sizeof(wfd_oem_invite_param_s));
564         param.ifname = strdup(group->ifname);
565         memcpy(param.go_dev_addr, group->go_dev_addr, MACADDR_LEN);
566
567         WDS_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]",
568                                 MAC2STR(peer->dev_addr), MAC2STR(param.go_dev_addr));
569
570         res = wfd_oem_invite(manager->oem_ops, peer->dev_addr, &param);
571         if (res < 0) {
572                 WDS_LOGE("Failed to invite with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
573                 wfd_destroy_session(manager);
574                 __WDS_LOG_FUNC_EXIT__;
575                 return -1;
576         }
577
578         wfd_session_timer(session, 1);
579
580         __WDS_LOG_FUNC_EXIT__;
581         return 0;
582 }
583
584 int wfd_session_wps(wfd_session_s *session)
585 {
586         __WDS_LOG_FUNC_ENTER__;
587         wfd_manager_s *manager = wfd_get_manager();
588         wfd_device_s *peer = NULL;
589         int res = 0;
590
591         if (!session) {
592                 WDS_LOGE("Invalid parameter");
593                 __WDS_LOG_FUNC_EXIT__;
594                 return -1;
595         }
596
597         if (session->state > SESSION_STATE_WPS) {
598                 WDS_LOGE("Session already starts WPS");
599                 return -1;
600         }
601
602         session->state = SESSION_STATE_WPS;
603         peer = session->peer;
604
605         if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
606                 WDS_LOGD("My device is GO, so WPS will be started. WPS mode[%d]", session->wps_mode);
607                 res = wfd_oem_wps_start(manager->oem_ops, peer->dev_addr, session->wps_mode, session->wps_pin);
608         } else {
609                 WDS_LOGD("My device is not GO, so Enrollee will be started. WPS mode[%d]", session->wps_mode);
610                 wfd_oem_conn_param_s param;
611                 memset(&param, 0x00, sizeof(wfd_oem_conn_param_s));
612                 param.wps_mode = session->wps_mode;
613                 param.conn_flags |= WFD_OEM_CONN_TYPE_JOIN;
614                 param.freq = session->freq;     /* currently not used */
615                 g_strlcpy(param.wps_pin, session->wps_pin, OEM_PINSTR_LEN + 1);
616                 res = wfd_oem_connect(manager->oem_ops, peer->dev_addr, &param);
617         }
618         if (res < 0) {
619                 WDS_LOGE("Failed to start wps with peer [" MACSECSTR "]", MAC2SECSTR(peer->dev_addr));
620                 wfd_destroy_session(manager);
621                 __WDS_LOG_FUNC_EXIT__;
622                 return -1;
623         }
624
625         __WDS_LOG_FUNC_EXIT__;
626         return 0;
627 }
628
629 wfd_device_s *wfd_session_get_peer(wfd_session_s *session)
630 {
631         __WDS_LOG_FUNC_ENTER__;
632         wfd_device_s *peer = NULL;
633
634         if (!session) {
635                 WDS_LOGE("Invalid parameter");
636                 return NULL;
637         }
638
639         peer = session->peer;
640
641         __WDS_LOG_FUNC_EXIT__;
642         return peer;
643 }
644
645 unsigned char *wfd_session_get_peer_addr(wfd_session_s *session)
646 {
647         __WDS_LOG_FUNC_ENTER__;
648         wfd_device_s *peer = NULL;
649
650         if (!session || !session->peer) {
651                 WDS_LOGE("Invalid parameter");
652                 return NULL;
653         }
654
655         peer = session->peer;
656
657         __WDS_LOG_FUNC_EXIT__;
658         return peer->dev_addr;
659 }
660
661 #if 0
662 int wfd_session_get_wps_pin(wfd_session_s *session, unsigned char *pin)
663 {
664         __WDS_LOG_FUNC_ENTER__;
665
666         __WDS_LOG_FUNC_EXIT__;
667         return 0;
668 }
669
670 int wfd_session_set_wps_pin(wfd_session_s *session, unsigned char *pin)
671 {
672         __WDS_LOG_FUNC_ENTER__;
673
674         __WDS_LOG_FUNC_EXIT__;
675         return 0;
676 }
677
678 int wfd_session_set_freq(wfd_session_s *session, int freq)
679 {
680         __WDS_LOG_FUNC_ENTER__;
681
682         __WDS_LOG_FUNC_EXIT__;
683         return 0;
684 }
685
686 int wfd_session_get_state(wfd_session_s *session)
687 {
688         __WDS_LOG_FUNC_ENTER__;
689
690         __WDS_LOG_FUNC_EXIT__;
691         return 0;
692 }
693
694 int wfd_session_set_state(wfd_session_s *session, int state)
695 {
696         __WDS_LOG_FUNC_ENTER__;
697
698         __WDS_LOG_FUNC_EXIT__;
699         return 0;
700 }
701 #endif
702
703 int wfd_session_process_event(wfd_manager_s *manager, wfd_oem_event_s *event)
704 {
705         __WDS_LOG_FUNC_ENTER__;
706         wfd_session_s *session = NULL;
707         int res = 0;
708
709         if (!manager || !event) {
710                 WDS_LOGE("Invalid parameter");
711                 return -1;
712         }
713
714         WDS_LOGD("event ID [%d]", event->event_id);
715         session = manager->session;
716
717         switch (event->event_id) {
718         case WFD_OEM_EVENT_PROV_DISC_REQ:
719         {
720                 int req_wps_mode = WFD_WPS_MODE_NONE;
721
722                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
723                         req_wps_mode = WFD_WPS_MODE_KEYPAD;
724                 else if (event->wps_mode == WFD_WPS_MODE_KEYPAD)
725                         req_wps_mode = WFD_WPS_MODE_DISPLAY;
726                 else
727                         req_wps_mode = WFD_WPS_MODE_PBC;
728
729                 /* Only peer initiated connection or invitation session can be allowed */
730                 if (session) {
731                         if (session->type != SESSION_TYPE_INVITE) {
732                                 WDS_LOGE("Unexpected event. Session is exist [peer: " MACSECSTR "]",
733                                                                 MAC2SECSTR(event->dev_addr));
734                                 break;
735                         }
736                         WDS_LOGD("=====> session already exist. (invitation session)");
737                         session->req_wps_mode = req_wps_mode;
738                         session->wps_mode = event->wps_mode;
739                 } else {
740                         session = wfd_create_session(manager, event->dev_addr,
741                                                                 req_wps_mode, SESSION_DIRECTION_INCOMING);
742                         if (!session) {
743                                 WDS_LOGE("Failed to create session with peer [" MACSECSTR "]",
744                                                                 MAC2SECSTR(event->dev_addr));
745                                 break;
746                         }
747                 }
748
749                 /* Update session */
750                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY)
751                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
752
753                 session->state = SESSION_STATE_STARTED;
754                 if (session->type == SESSION_TYPE_INVITE)
755                         WDS_LOGD("Invitation session");
756                 else if (WFD_DEV_ROLE_GO == manager->local->dev_role)
757                         session->type = SESSION_TYPE_JOIN;
758                 else
759                         session->type = SESSION_TYPE_NORMAL;
760
761                 wfd_session_timer(session, 1);
762
763                 /* Update local device */
764                 manager->local->wps_mode = event->wps_mode;
765
766                 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
767
768                 if (session->type == SESSION_TYPE_INVITE) {
769                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
770                         if (session->wps_mode != WFD_WPS_MODE_PBC) {
771                                 char peer_mac_address[MACSTR_LEN+1] = {0, };
772
773                                 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
774                                 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
775                                                              "Connection",
776                                                              g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
777                                                                                     WFD_EVENT_CONNECTION_WPS_REQ,
778                                                                                     peer_mac_address));
779                                 if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
780                                         /* We have to wait until user type PIN using Keypad */
781                                         break;
782                                 }
783                         }
784                         res = wfd_session_wps(session);
785                         if (res < 0)
786                                 _wfd_notify_session_failed(manager, event->dev_addr);
787                 } else {
788                         char peer_mac_address[MACSTR_LEN+1] = {0, };
789
790                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
791                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
792                                                      "Connection",
793                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
794                                                                             WFD_EVENT_CONNECTION_REQ,
795                                                                             peer_mac_address));
796                 }
797         }
798         break;
799         case WFD_OEM_EVENT_PROV_DISC_RESP:
800         {
801                 if (!session) {         /* TODO: check validity of Event */
802                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
803                                                                                 MAC2SECSTR(event->dev_addr));
804                         break;
805                 }
806
807                 if (session->state > SESSION_STATE_STARTED) {
808                         WDS_LOGE("Unexpected event. Session is already started");
809                         break;
810                 }
811
812                 if (session->type == SESSION_TYPE_INVITE) {
813                         WDS_LOGE("Session type is invite, ignore provision discovery response");
814                         break;
815                 }
816
817                 /* Update session */
818                 session->wps_mode = event->wps_mode;
819                 if (event->wps_mode == WFD_WPS_MODE_DISPLAY) {
820                         session->req_wps_mode = WFD_WPS_MODE_KEYPAD;
821                         g_strlcpy(session->wps_pin, event->wps_pin, PINSTR_LEN + 1);
822                 } else if (event->wps_mode == WFD_WPS_MODE_KEYPAD) {
823                         session->req_wps_mode = WFD_WPS_MODE_DISPLAY;
824                 } else {
825                         session->req_wps_mode = WFD_WPS_MODE_PBC;
826                 }
827
828                 session->state = SESSION_STATE_STARTED;
829                 wfd_session_timer(session, 1);
830
831                 /* Update local device */
832                 manager->local->wps_mode = event->wps_mode;
833                 WDS_LOGD("Local WPS mode is %d", session->wps_mode);
834
835                 if (session->wps_mode != WFD_WPS_MODE_PBC) {
836                         char peer_mac_address[MACSTR_LEN+1] = {0, };
837
838                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
839                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
840                                                      "Connection",
841                                                      g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
842                                                                             WFD_EVENT_CONNECTION_WPS_REQ,
843                                                                             peer_mac_address));
844                         if (session->wps_mode == WFD_WPS_MODE_KEYPAD) {
845                                 /* We have to wait until user type PIN using Keypad */
846                                 break;
847                         }
848                 }
849
850                 if (manager->local->dev_role == WFD_DEV_ROLE_GO) {
851                         WDS_LOGD("Start WPS corresponding to OEM event [%d]", event->event_id);
852                         res = wfd_session_wps(session);
853                 } else if (session->peer->dev_role == WFD_DEV_ROLE_GO) {
854                         WDS_LOGD("Start WPS(join) corresponding to OEM event [%d]", event->event_id);
855                         res = wfd_session_join(session);
856                 } else {
857                         WDS_LOGD("Start connection corresponding to OEM event [%d]", event->event_id);
858                         res = wfd_session_connect(session);
859                 }
860
861                 if (res < 0)
862                         _wfd_notify_session_failed(manager, event->dev_addr);
863         }
864         break;
865         case WFD_OEM_EVENT_GO_NEG_REQ:
866         {
867                 if (!session) {
868                         session = wfd_create_session(manager, event->dev_addr,
869                                         event->wps_mode, SESSION_DIRECTION_INCOMING);
870                         if (!session) {
871                                 WDS_LOGE("Failed to create session");
872                                 __WDS_LOG_FUNC_EXIT__;
873                                 break;
874                         }
875
876                         session->type = SESSION_TYPE_NORMAL;
877                         session->state = SESSION_STATE_GO_NEG;
878                         wfd_session_timer(session, 1);
879                         wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTING);
880
881                         char peer_mac_address[MACSTR_LEN+1] = {0, };
882                         g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(event->dev_addr));
883                         wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
884                                         "Connection",
885                                         g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
886                                                 WFD_EVENT_CONNECTION_REQ,
887                                                 peer_mac_address));
888                 } else {
889                         /* Sometimes, Provision Discovery response is not received.
890                          * At this time, connection should be triggered by GO Negotiation request event */
891                         if (session->direction == SESSION_DIRECTION_OUTGOING) {
892                                 res = wfd_session_connect(session);
893                         } else {
894                                 /* In autoconnection mode, MT should not send GO Nego Req
895                                    before receiving the GO Nego Req from peer (MO). */
896                                 if (manager->autoconnection == TRUE)
897                                         res  = wfd_session_connect(session);
898                         }
899                         if (res < 0)
900                                 _wfd_notify_session_failed(manager, event->dev_addr);
901                 }
902         }
903         break;
904         case WFD_OEM_EVENT_GO_NEG_DONE:
905         {
906                 if (!session) {
907                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
908                                         MAC2SECSTR(event->dev_addr));
909                         break;
910                 } else {
911                         manager->local->dev_role = event->dev_role;
912                         session->state = SESSION_STATE_WPS;
913                 }
914         }
915         break;
916         case WFD_OEM_EVENT_WPS_DONE:
917         {
918                 if (!session) {
919                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
920                                         MAC2SECSTR(event->dev_addr));
921                         break;
922                 } else {
923                         session->state = SESSION_STATE_KEY_NEG;
924                 }
925         }
926         break;
927         case WFD_OEM_EVENT_STA_CONNECTED:
928         {
929                 if (!session) {
930                         WDS_LOGE("Unexpected event. Session is NULL [peer: " MACSECSTR "]",
931                                         MAC2SECSTR(event->dev_addr));
932                         break;
933                 } else {
934                         session->state = SESSION_STATE_COMPLETED;
935                 }
936         }
937         break;
938         default:
939                 break;
940         }
941         __WDS_LOG_FUNC_EXIT__;
942         return 0;
943 }