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