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 wpasupplicant plugin functions.
23 * @file wfd_plugin_wpasupplicant.c
24 * @author Gibyoung Kim (lastkgb.kim@samsung.com)
31 #include <sys/types.h>
32 #include <sys/socket.h>
39 #include <sys/ioctl.h>
44 #include "wifi-direct-oem.h"
45 #include "wfd-plugin-wpasupplicant.h"
47 ws_string_s ws_event_strs[] = {
49 {"P2P-DEVICE-FOUND", WS_EVENT_DEVICE_FOUND},
50 {"P2P-DEVICE-LOST", WS_EVENT_DEVICE_LOST},
51 {"P2P-FIND-STOPPED", WS_EVENT_FIND_STOPED},
53 // provision discovery
54 {"P2P-PROV-DISC-PBC-REQ", WS_EVENT_PROV_DISC_PBC_REQ},
55 {"P2P-PROV-DISC-SHOW-PIN", WS_EVENT_PROV_DISC_SHOW_PIN},
56 {"P2P-PROV-DISC-ENTER-PIN", WS_EVENT_PROV_DISC_ENTER_PIN},
57 {"P2P-PROV-DISC-PBC-RESP", WS_EVENT_PROV_DISC_PBC_RESP},
58 {"P2P-PROV-DISC-FAILURE", WS_EVENT_PROV_DISC_FAILURE},
61 {"P2P-GO-NEG-REQUEST", WS_EVENT_GO_NEG_REQUEST},
62 {"P2P-GO-NEG-FAILURE", WS_EVENT_GO_NEG_FAILURE},
63 {"P2P-GO-NEG-SUCCESS", WS_EVENT_GO_NEG_SUCCESS},
64 {"WPS-FAIL", WS_EVENT_WPS_FAIL},
65 {"P2P-GROUP-FORMATION-FAILURE", WS_EVENT_GROUP_FORMATION_FAILURE},
66 {"WPS-SUCCESS", WS_EVENT_WPS_SUCCESS},
67 {"WPS-REG-SUCCESS", WS_EVENT_WPS_REG_SUCCESS},
68 {"P2P-GROUP-FORMATION-SUCCESS", WS_EVENT_GROUP_FORMATION_SUCCESS},
70 {"CTRL-EVENT-CONNECTED", WS_EVENT_CONNECTED},
71 {"AP-STA-CONNECTED", WS_EVENT_STA_CONNECTED},
74 {"P2P-INVITATION-RECEIVED", WS_EVENT_INVITATION_RECEIVED},
75 {"P2P-INVITATION-RESULT", WS_EVENT_INVITATION_RESULT},
77 {"CTRL-EVENT-DISCONNECTED", WS_EVENT_DISCONNECTED},
78 {"AP-STA-DISCONNECTED", WS_EVENT_STA_DISCONNECTED},
81 {"P2P-GROUP-STARTED", WS_EVENT_GROUP_STARTED},
82 {"P2P-GROUP-REMOVED", WS_EVENT_GROUP_REMOVED},
84 {"CTRL-EVENT-TERMINATING", WS_EVENT_TERMINATING},
87 ws_string_s ws_dev_info_strs[] = {
88 {"p2p_dev_addr", WS_DEV_INFO_P2P_DEV_ADDR},
89 {"name", WS_DEV_INFO_DEV_NAME},
90 {"pri_dev_type", WS_DEV_INFO_DEV_TYPE},
91 {"config_methods", WS_DEV_INFO_CONFIG_METHODS},
92 {"dev_capab", WS_DEV_INFO_DEV_CAP},
93 {"group_capab", WS_DEV_INFO_GROUP_CAP},
94 {"p2p_go_addr", WS_DEV_INFO_P2P_GO_ADDR},
95 {"", WS_DEV_INFO_LIMIT},
98 ws_string_s ws_conn_info_strs[] = {
99 {"dev_passwd_id", WS_CONN_INFO_DEV_PWD_ID},
100 {"status", WS_CONN_INFO_STATUS},
101 {"config_error", WS_CONN_INFO_ERROR},
102 {"", WS_CONN_INFO_LIMIT},
105 ws_string_s ws_invite_info_strs[] = {
106 {"sa", WS_INVITE_INFO_SRC_ADDR},
107 {"go_dev_addr", WS_INVITE_INFO_GO_DEV_ADDR},
108 {"bssid", WS_INVITE_INFO_BSSID},
109 {"listen", WS_INVITE_INFO_LISTEN},
110 {"status", WS_INVITE_INFO_STATUS},
111 {"", WS_INVITE_INFO_LIMIT},
114 ws_string_s ws_group_info_strs[] = {
115 {"ssid", WS_GROUP_INFO_SSID},
116 {"freq", WS_GROUP_INFO_FREQ},
117 {"passphrase", WS_GROUP_INFO_PASS},
118 {"go_dev_addr", WS_GROUP_INFO_GO_DEV_ADDR},
119 {"status", WS_GROUP_INFO_STATUS},
120 {"", WS_GROUP_INFO_LIMIT},
124 ws_string_s ws_peer_info_strs[] = {
125 {"age", WS_PEER_INFO_AGE},
126 {"listen_freq", WS_PEER_INFO_LISTEN_FREQ},
127 {"level", WS_PEER_INFO_LEVEL},
128 {"wps_method", WS_PEER_INFO_WPS_METHOD},
129 {"interface_addr", WS_PEER_INFO_INTERFACE_ADDR},
130 {"member_in_go_dev", WS_PEER_INFO_MEMBER_IN_GO_DEV},
131 {"member_in_go_iface", WS_PEER_INFO_MEMBER_IN_GO_IFACE},
132 {"pri_dev_type", WS_PEER_INFO_PRI_DEV_TYPE},
133 {"device_name", WS_PEER_INFO_DEVICE_NAME},
134 {"manufacturer", WS_PEER_INFO_MANUFACTURER},
135 {"model_name", WS_PEER_INFO_MODEL_NAME},
136 {"model_number", WS_PEER_INFO_MODEL_NUMBER},
137 {"serial_number", WS_PEER_INFO_SERIAL_NUMBER},
138 {"config_methods", WS_PEER_INFO_CONFIG_METHODS},
139 {"dev_capab", WS_PEER_INFO_DEV_CAPAB},
140 {"group_capab", WS_PEER_INFO_GROUP_CAPAB},
141 {"is_wfd_device", WS_PEER_INFO_IS_WFD_DEVICE},
142 {"go_neg_req_sent", WS_PEER_INFO_GO_NEG_REQ_SENT},
143 {"go_state", WS_PEER_INFO_GO_STATE},
144 {"dialog_token", WS_PEER_INFO_DIALOG_TOKEN},
145 {"intended_addr", WS_PEER_INFO_INTENDED_ADDR},
146 {"country", WS_PEER_INFO_COUNTRY},
147 {"oper_freq", WS_PEER_INFO_OPER_FREQ},
148 {"req_config_methods", WS_PEER_INFO_REQ_CONFIG_METHODS},
149 {"flags", WS_PEER_INFO_FLAGS},
150 {"status", WS_PEER_INFO_STATUS},
151 {"wait_count", WS_PEER_INFO_WAIT_COUNT},
152 {"invitation_reqs", WS_PEER_INFO_INVITATION_REQS},
155 static wfd_oem_ops_s supplicant_ops = {
158 .activate = ws_activate,
159 .deactivate = ws_deactivate,
161 .start_scan = ws_start_scan,
162 .stop_scan = ws_stop_scan,
163 .get_visibility = ws_get_visibility,
164 .set_visibility = ws_set_visibility,
165 .get_scan_result = ws_get_scan_result,
166 .get_peer_info = ws_get_peer_info,
168 .prov_disc_req = ws_prov_disc_req,
170 .connect = ws_connect,
171 .disconnect = ws_disconnect,
172 .reject_connection = ws_reject_connection,
173 .cancel_connection = ws_cancel_connection,
175 .get_connected_peers = ws_get_connected_peers,
176 .get_pin = ws_get_pin,
177 .set_pin = ws_set_pin,
178 .get_supported_wps_mode = ws_get_supported_wps_mode,
180 .create_group = ws_create_group,
181 .destroy_group = ws_destroy_group,
183 .wps_start = ws_wps_start,
184 .enrollee_start = ws_enrollee_start,
185 .wps_cancel = ws_wps_cancel,
187 .get_dev_name = ws_get_dev_name,
188 .set_dev_name = ws_set_dev_name,
189 .get_dev_mac = ws_get_dev_mac,
190 .get_dev_type = ws_get_dev_type,
191 .set_dev_type = ws_set_dev_type,
192 .get_go_intent = ws_get_go_intent,
193 .set_go_intent = ws_set_go_intent,
194 .get_persistent_groups = ws_get_persistent_groups,
195 .remove_persistent_group = ws_remove_persistent_group,
196 .set_persistent_reconnect = ws_set_persistent_reconnect,
199 static ws_plugin_data_s *g_pd;
201 static gboolean ws_event_handler(GIOChannel *source,
202 GIOCondition condition,
205 int wfd_plugin_load(wfd_oem_ops_s **ops)
208 WDP_LOGE("Invalid parameter");
212 *ops = &supplicant_ops;
217 static int _ws_txt_to_devtype(char *txt, int *pri, int *sec)
219 if (!txt || !pri || !sec) {
220 WDP_LOGE("Invalid parameter");
224 if (strlen(txt) > WS_DEVTYPESTR_LEN) {
225 WDP_LOGE("Device type string is invalid [%s]", txt);
229 *pri = (int) strtoul(txt, &txt, 0);
230 txt = strrchr(txt, '-');
231 *sec = (int) strtoul(txt+1, &txt, 16);
236 static int _ws_txt_to_mac(char *txt, unsigned char *mac)
241 WDP_LOGE("Invalid parameter");
246 mac[i++] = (char) strtoul(txt, &txt, 16);
247 if (!*txt++ || i == 6)
251 if (i != OEM_MACADDR_LEN)
257 static char *_ws_wps_to_txt(int wps_mode)
260 case WFD_OEM_WPS_MODE_PBC:
263 case WFD_OEM_WPS_MODE_DISPLAY:
264 return WS_STR_DISPLAY;
266 case WFD_OEM_WPS_MODE_KEYPAD:
267 return WS_STR_KEYPAD;
275 static int _ws_freq_to_channel(int freq)
277 if (freq < 2412 || freq > 5825) {
278 WDP_LOGE("Invalid parameter");
283 return 36 + (freq - 5180)/5;
284 else if (freq <= 2472)
285 return 1 + (freq - 2412)/5;
286 else if (freq == 2484)
292 gboolean _ws_util_execute_file(const char *file_path,
293 char *const args[], char *const envs[])
298 register unsigned int index = 0;
300 while (args[index] != NULL) {
301 WDP_LOGD("[%s]", args[index]);
305 if (!(pid = fork())) {
306 WDP_LOGD("pid(%d), ppid(%d)", getpid(), getppid());
307 WDP_LOGD("Inside child, exec (%s) command", file_path);
310 if (execve(file_path, args, envs) == -1) {
311 WDP_LOGE("Fail to execute command (%s)", strerror(errno));
314 } else if (pid > 0) {
315 if (waitpid(pid, &rv, 0) == -1)
316 WDP_LOGD("wait pid (%u) rv (%d)", pid, rv);
318 WDP_LOGD("exited, rv=%d", WEXITSTATUS(rv));
319 } else if (WIFSIGNALED(rv)) {
320 WDP_LOGD("killed by signal %d", WTERMSIG(rv));
321 } else if (WIFSTOPPED(rv)) {
322 WDP_LOGD("stopped by signal %d", WSTOPSIG(rv));
323 } else if (WIFCONTINUED(rv)) {
324 WDP_LOGD("continued");
330 WDP_LOGE("failed to fork (%s)", strerror(errno));
334 static int _ws_check_socket(int sock)
340 p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
341 res = poll((struct pollfd *) &p_fd, 1, 1);
344 WDP_LOGE("Polling error from socket[%d]. [%s]", sock, strerror(errno));
346 } else if (res == 0) {
347 WDP_LOGD( "poll timeout. socket is busy\n");
351 if (p_fd.revents & POLLERR) {
352 WDP_LOGF("Error! POLLERR from socket[%d]", sock);
354 } else if (p_fd.revents & POLLHUP) {
355 WDP_LOGF("Error! POLLHUP from socket[%d]", sock);
357 } else if (p_fd.revents & POLLNVAL) {
358 WDP_LOGF("Error! POLLNVAL from socket[%d]", sock);
360 } else if (p_fd.revents & POLLIN) {
361 WDP_LOGD("POLLIN from socket [%d]", sock);
363 } else if (p_fd.revents & POLLOUT) {
364 WDP_LOGD("POLLOUT from socket [%d]", sock);
369 WDP_LOGD("Unknown poll event [%d]", p_fd.revents);
373 static int _ws_read_sock(int sock, char *data, int data_len)
375 __WDP_LOG_FUNC_ENTER__;
380 if(sock < SOCK_FD_MIN || !data || data_len <= 0) {
381 WDP_LOGE("Invalid parameter");
386 p_fd.events = POLLIN | POLLERR | POLLHUP;
387 p_ret = poll(&p_fd, 1, WS_POLL_TIMEOUT);
391 if (p_fd.revents & POLLIN) {
392 WDP_LOGD("POLLIN from socket [%d]", sock);
394 rbytes = read(sock, data, data_len);
396 WDP_LOGE("Failed to read data from socket[%d]. [%s]", sock, strerror(errno));
399 WDP_LOGD("===== Read Data =====\n%s", data);
400 data[data_len-1] = '\0';
401 __WDP_LOG_FUNC_EXIT__;
403 } else if (p_fd.revents & POLLERR) {
404 WDP_LOGE("Error! POLLERR from socket[%d]", sock);
406 } else if (p_fd.revents & POLLHUP) {
407 WDP_LOGE("Error! POLLHUP from socket[%d]", sock);
410 } else if (p_ret == 0) {
411 WDP_LOGE("Polling timeout from socket[%d]", sock);
413 WDP_LOGE("Polling error from socket[%d]. [%s]", sock, strerror(errno));
416 __WDP_LOG_FUNC_EXIT__;
420 static int _ws_send_cmd(int sock, char *cmd, char *reply, int reply_len)
422 __WDP_LOG_FUNC_ENTER__;
426 if (sock < SOCK_FD_MIN || !cmd || !reply || reply_len < 0) {
427 WDP_LOGE("Invalid parameter");
430 WDP_LOGI("Sending command [%s]", cmd);
432 res = _ws_check_socket(sock);
434 WDP_LOGE("Socket error");
436 } else if (res > 0) {
437 WDP_LOGE("Socket is busy");
442 wbytes = write(sock, cmd, strlen(cmd));
444 WDP_LOGE("Failed to write into socket[%d]. [%s]", sock, strerror(errno));
448 res = _ws_read_sock(sock, reply, reply_len);
450 WDP_LOGE("Failed to read return for command");
451 __WDP_LOG_FUNC_EXIT__;
455 __WDP_LOG_FUNC_EXIT__;
459 static int _ws_flush()
461 __WDP_LOG_FUNC_ENTER__;
462 ws_sock_data_s *sock = g_pd->common;
463 char reply[1024]={0,};
467 WDP_LOGE("Socket is NULL");
471 res = _ws_send_cmd(sock->ctrl_sock, WS_CMD_P2P_FLUSH, reply, sizeof(reply));
473 WDP_LOGE("Failed to send command to wpa_supplicant");
474 __WDP_LOG_FUNC_EXIT__;
478 if (strstr(reply, "FAIL")) {
479 WDP_LOGE("Failed to flush");
480 __WDP_LOG_FUNC_EXIT__;
483 WDP_LOGD("Succeeded to flush");
485 __WDP_LOG_FUNC_EXIT__;
489 static int _ws_cancel()
491 __WDP_LOG_FUNC_ENTER__;
492 ws_sock_data_s *sock = g_pd->common;
493 char reply[1024]={0,};
497 WDP_LOGE("Socket is NULL");
501 res = _ws_send_cmd(sock->ctrl_sock, WS_CMD_P2P_CANCEL, reply, sizeof(reply));
503 WDP_LOGE("Failed to send command to wpa_supplicant");
504 __WDP_LOG_FUNC_EXIT__;
508 if (strstr(reply, "FAIL")) {
509 WDP_LOGE("Failed to cancel");
510 __WDP_LOG_FUNC_EXIT__;
513 WDP_LOGD("Succeeded to cancel");
515 __WDP_LOG_FUNC_EXIT__;
519 static int _create_ctrl_intf(char *ctrl_intf_path, char *supp_path)
521 __WDP_LOG_FUNC_ENTER__;
522 struct sockaddr_un srv_addr;
523 struct sockaddr_un local_addr;
527 if(!ctrl_intf_path || !supp_path) {
528 WDP_LOGE("Invalid parameter");
531 unlink(ctrl_intf_path);
534 sock = socket(AF_UNIX, SOCK_DGRAM, 0);
535 if (sock < SOCK_FD_MIN) {
536 WDP_LOGE("Failed to create socket. [%s]", strerror(errno));
539 __WDP_LOG_FUNC_EXIT__;
542 WDP_LOGI( "Succeeded to create socket [%d]\n", sock);
544 memset(&srv_addr, 0, sizeof(srv_addr));
545 srv_addr.sun_family = AF_UNIX;
546 snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), supp_path);
548 memset(&local_addr, 0, sizeof(local_addr));
549 local_addr.sun_family = AF_UNIX;
550 snprintf(local_addr.sun_path, sizeof(local_addr.sun_path), ctrl_intf_path);
552 res = bind(sock, (struct sockaddr*) &local_addr, sizeof(local_addr));
555 WDP_LOGE("Failed to bind local socket [%s]. Try again...", strerror(errno));
556 unlink(ctrl_intf_path);
559 __WDP_LOG_FUNC_EXIT__;
564 res = connect(sock, (struct sockaddr*) &srv_addr, sizeof(srv_addr));
566 WDP_LOGE("Failed to connect to server socket [%s]", strerror(errno));
568 __WDP_LOG_FUNC_EXIT__;
571 WDP_LOGI("Succeeded to connect to server socket [%d]", sock);
573 __WDP_LOG_FUNC_EXIT__;
577 static int _attach_mon_intf(int sock)
579 __WDP_LOG_FUNC_ENTER__;
584 if (sock < SOCK_FD_MIN) {
585 WDP_LOGE("Invalid parameter");
589 snprintf(cmd, sizeof(cmd), WS_CMD_ATTACH);
590 res = _ws_send_cmd(sock, cmd, reply, sizeof(reply));
592 WDP_LOGE("Failed to send command to wpa_supplicant");
593 __WDP_LOG_FUNC_EXIT__;
597 if (strstr(reply, "FAIL")) {
598 WDP_LOGE( "Failed to operate command(wpa_supplicant)");
599 __WDP_LOG_FUNC_EXIT__;
603 __WDP_LOG_FUNC_EXIT__;
607 static int _connect_to_supplicant(char *ifname, ws_sock_data_s **sock_data)
609 __WDP_LOG_FUNC_ENTER__;
610 ws_sock_data_s *sock = NULL;
613 char ctrl_path[32] = {0, };
614 char mon_path[32] = {0, };
615 char suppl_path[40] = {0, };
619 if (!ifname || !sock_data) {
620 WDP_LOGE("Invalie parameter");
621 __WDP_LOG_FUNC_EXIT__;
625 if (sock && sock->ctrl_sock > SOCK_FD_MIN) {
626 WDP_LOGE("Socket already connected [%d]", sock->ctrl_sock);
631 sock = (ws_sock_data_s*) calloc(1, sizeof(ws_sock_data_s));
633 WDP_LOGE("Failed to allocate memory for socket data", strerror(errno));
634 __WDP_LOG_FUNC_EXIT__;
638 snprintf(ctrl_path, sizeof(ctrl_path), "/tmp/%s_control", ifname);
639 snprintf(mon_path, sizeof(mon_path), "/tmp/%s_monitor", ifname);
640 snprintf(suppl_path, sizeof(suppl_path), SUPPL_IFACE_PATH "%s", ifname);
642 for(i = 0; i < WS_CONN_RETRY_COUNT; i++) {
643 ctrl_sock = _create_ctrl_intf(ctrl_path, suppl_path);
644 if (ctrl_sock < SOCK_FD_MIN) {
645 WDP_LOGE("Failed to create control interface socket for %s", ifname);
648 WDP_LOGD("Succeeded to create control interface socket[%d] for %s", ctrl_sock, ifname);
650 mon_sock = _create_ctrl_intf(mon_path, suppl_path);
651 if (mon_sock < SOCK_FD_MIN) {
652 WDP_LOGE("Failed to create monitor interface socket for %s", ifname);
657 WDP_LOGD("Succeeded to create monitor interface socket[%d] for %s", mon_sock, ifname);
659 res = _attach_mon_intf(mon_sock);
661 WDP_LOGE("Failed to attach monitor interface for event");
668 WDP_LOGD("Succeeded to attach monitor interface for event");
672 if (i == WS_CONN_RETRY_COUNT) {
679 __WDP_LOG_FUNC_EXIT__;
683 sock->ctrl_sock = ctrl_sock;
684 sock->mon_sock = mon_sock;
685 sock->ifname = strdup(ifname);
689 gio = g_io_channel_unix_new(mon_sock);
690 gsource = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP, (GIOFunc) ws_event_handler, sock);
691 g_io_channel_unref(gio);
693 sock->gsource = gsource;
696 __WDP_LOG_FUNC_EXIT__;
700 static gboolean _remove_event_source(gpointer data)
702 __WDP_LOG_FUNC_ENTER__;
703 int source_id = (int) data;
707 WDP_LOGE("Invalid source ID [%d]", source_id);
711 res = g_source_remove(source_id);
713 WDP_LOGE("Failed to remove GSource");
716 WDP_LOGD("Succeeded to remove GSource");
718 __WDP_LOG_FUNC_EXIT__;
722 static int _disconnect_from_supplicant(char *ifname, ws_sock_data_s *sock_data)
724 __WDP_LOG_FUNC_ENTER__;
726 char ctrl_path[32] = {0, };
727 char mon_path[32] = {0, };
729 char reply[1024] = {0, };
731 if (!ifname || !sock_data) {
732 WDP_LOGE("Invalie parameter");
736 // detach monitor interface
737 snprintf(cmd, sizeof(cmd), WS_CMD_DETACH);
738 res = _ws_send_cmd(sock_data->mon_sock, cmd, reply, sizeof(reply));
740 WDP_LOGE("Failed to send command to wpa_supplicant. Keep going to close socket.");
742 if (!strncmp(reply, "FAIL", 4)) {
743 WDP_LOGE( "Failed to detach monitor sock [%d]", sock_data->mon_sock);
744 // TODO: I think there is no need to exit
745 __WDP_LOG_FUNC_EXIT__;
748 WDP_LOGD("Succeeded to detach monitor sock for %s", ifname ? ifname : "NULL");
751 if (sock_data->gsource > 0)
752 g_idle_add(_remove_event_source, (gpointer) sock_data->gsource);
753 sock_data->gsource = 0;
755 // close control interface
756 snprintf(ctrl_path, sizeof(ctrl_path), "/tmp/%s_control", ifname);
757 snprintf(mon_path, sizeof(mon_path), "/tmp/%s_monitor", ifname);
759 if (sock_data->ctrl_sock >= SOCK_FD_MIN)
760 close(sock_data->ctrl_sock);
761 sock_data->ctrl_sock = -1;
764 if (sock_data->mon_sock >= SOCK_FD_MIN)
765 close(sock_data->mon_sock);
766 sock_data->mon_sock = -1;
769 if (sock_data->ifname)
770 free(sock_data->ifname);
774 __WDP_LOG_FUNC_EXIT__;
778 static int _extract_word(const char *data, char **value)
782 if(!data || !value) {
783 WDP_LOGE("Invalid parameter");
787 for(i = 0; data[i]; i++) {
788 if(data[i] == '\n' || data[i] == '\r' || data[i] == ' ' || data[i] == '\t') {
794 *value = (char*) calloc(1, i+1);
795 strncpy(*value, data, i);
802 static int _extract_value_str(const char *data, const char *key, char **value)
804 char *tmp_str = NULL;
807 if(!data || !key || !value) {
808 WDP_LOGE("Invalid parameter");
812 tmp_str = strstr(data, key);
814 WDP_LOGE("Key[%s] is not found", key);
817 tmp_str = tmp_str + strlen(key) + 1;
819 if (tmp_str[0] == '\'' || tmp_str[0] == '\"') {
821 for(i = 0; tmp_str[i]; i++) {
822 if(tmp_str[i] == '\'' || tmp_str[i] == '\"')
826 for(i = 0; tmp_str[i]; i++) {
827 if(tmp_str[i] == '\n' || tmp_str[i] == '\r' || tmp_str[i] == ' ')
833 *value = (char*) calloc(1, i+1);
834 strncpy(*value, tmp_str, i);
836 WDP_LOGV("Extracted string: %s", *value);
843 static int _extract_peer_value_str(const char *data, const char *key, char **value)
845 char *tmp_str = NULL;
848 if(!data || !key || !value) {
849 WDP_LOGE("Invalid parameter");
853 tmp_str = strstr(data, key);
855 WDP_LOGE("Key[%s] is not found", key);
858 tmp_str = tmp_str + strlen(key) + 1;
860 for(i = 0; tmp_str[i]; i++) {
861 if(tmp_str[i] == '\n' || tmp_str[i] == '\r')
866 *value = (char*) calloc(1, i+1);
867 strncpy(*value, tmp_str, i);
869 WDP_LOGV("Extracted string: %s", *value);
876 static int _parsing_peer_info(char *msg, wfd_oem_device_s *peer)
878 __WDP_LOG_FUNC_ENTER__;
880 ws_string_s infos[WS_PEER_INFO_LIMIT];
881 int config_methods = 0x00;
882 int group_capab = 0x00;
886 WDP_LOGE("Invalid parameter");
890 _ws_txt_to_mac(msg, peer->dev_addr);
891 msg += OEM_MACSTR_LEN;
893 memset(infos, 0x0, (WS_PEER_INFO_LIMIT) * sizeof(ws_string_s));
894 for (i = 0; i < WS_PEER_INFO_LIMIT; i++) {
895 res = _extract_peer_value_str(msg, ws_peer_info_strs[i].string, &infos[info_cnt].string);
897 infos[info_cnt].index = ws_peer_info_strs[i].index;
902 for (i = 0; i < info_cnt; i++) {
903 switch (infos[i].index){
904 case WS_PEER_INFO_AGE:
905 peer->age = (int) strtoul(infos[i].string, NULL, 10);
907 case WS_PEER_INFO_LISTEN_FREQ:
910 freq = (int) strtoul(infos[i].string, NULL, 10);
911 peer->channel = _ws_freq_to_channel(freq);
914 case WS_PEER_INFO_LEVEL:
916 case WS_PEER_INFO_WPS_METHOD:
918 case WS_PEER_INFO_INTERFACE_ADDR:
920 case WS_PEER_INFO_MEMBER_IN_GO_DEV:
922 res = _ws_txt_to_mac(infos[i].string, peer->go_dev_addr);
924 memset(peer->go_dev_addr, 0x00, OEM_MACADDR_LEN);
926 unsigned char null_mac[OEM_MACADDR_LEN] = {0, 0, 0, 0, 0, 0};
927 if (memcmp(peer->go_dev_addr, null_mac, OEM_MACADDR_LEN))
928 peer->dev_role = WFD_OEM_DEV_ROLE_GC;
931 case WS_PEER_INFO_MEMBER_IN_GO_IFACE:
933 case WS_PEER_INFO_PRI_DEV_TYPE:
934 res = _ws_txt_to_devtype(infos[i].string, &peer->pri_dev_type, &peer->sec_dev_type);
936 peer->pri_dev_type = 0;
937 peer->sec_dev_type = 0;
940 case WS_PEER_INFO_DEVICE_NAME:
941 strncpy(peer->dev_name, infos[i].string, OEM_DEV_NAME_LEN);
942 peer->dev_name[OEM_DEV_NAME_LEN] = '\0';
944 case WS_PEER_INFO_MANUFACTURER:
946 case WS_PEER_INFO_MODEL_NAME:
948 case WS_PEER_INFO_MODEL_NUMBER:
950 case WS_PEER_INFO_SERIAL_NUMBER:
952 case WS_PEER_INFO_CONFIG_METHODS:
953 config_methods = (int) strtoul(infos[i].string, NULL, 16);
954 if (config_methods & WS_CONFIG_METHOD_DISPLAY)
955 peer->config_methods |= WFD_OEM_WPS_MODE_DISPLAY;
956 if (config_methods & WS_CONFIG_METHOD_PUSHBUTTON)
957 peer->config_methods |= WFD_OEM_WPS_MODE_PBC;
958 if (config_methods & WS_CONFIG_METHOD_KEYPAD)
959 peer->config_methods |= WFD_OEM_WPS_MODE_KEYPAD;
961 case WS_PEER_INFO_DEV_CAPAB:
962 peer->dev_flags = (int) strtoul(infos[i].string, NULL, 16);
964 case WS_PEER_INFO_GROUP_CAPAB:
965 group_capab = (int) strtoul(infos[i].string, NULL, 16);
966 if (group_capab & WS_GROUP_CAP_GROUP_OWNER) {
967 peer->group_flags = WFD_OEM_GROUP_FLAG_GROUP_OWNER;
968 peer->dev_role = WFD_OEM_DEV_ROLE_GO;
970 if (group_capab & WS_GROUP_CAP_PERSISTENT_GROUP)
971 peer->group_flags = WFD_OEM_GROUP_FLAG_PERSISTENT_GROUP;
973 case WS_PEER_INFO_IS_WFD_DEVICE:
975 case WS_PEER_INFO_GO_NEG_REQ_SENT:
977 case WS_PEER_INFO_GO_STATE:
979 case WS_PEER_INFO_DIALOG_TOKEN:
981 case WS_PEER_INFO_INTENDED_ADDR:
982 res = _ws_txt_to_mac(infos[i].string, peer->intf_addr);
984 memset(peer->intf_addr, 0x00, OEM_MACADDR_LEN);
986 case WS_PEER_INFO_COUNTRY:
988 case WS_PEER_INFO_OPER_FREQ:
990 case WS_PEER_INFO_REQ_CONFIG_METHODS:
992 case WS_PEER_INFO_FLAGS:
994 case WS_PEER_INFO_STATUS:
996 case WS_PEER_INFO_WAIT_COUNT:
998 case WS_PEER_INFO_INVITATION_REQS:
1005 for(i = 0; i < info_cnt; i++) {
1006 if (infos[i].string)
1007 free(infos[i].string);
1010 __WDP_LOG_FUNC_EXIT__;
1014 static wfd_oem_dev_data_s *_convert_msg_to_dev_info(char *msg)
1016 __WDP_LOG_FUNC_ENTER__;
1019 ws_string_s infos[WS_DEV_INFO_LIMIT];
1020 wfd_oem_dev_data_s *edata = NULL;
1021 int config_methods = 0x00;
1022 int group_capab = 0x00;
1026 WDP_LOGE("Invalid parameter");
1029 WDP_LOGD("msg to be converted [%s]", msg);
1031 memset(infos, 0x0, (WS_DEV_INFO_LIMIT) * sizeof(ws_string_s));
1032 for (i = 0; i < WS_DEV_INFO_LIMIT; i++) {
1033 res = _extract_value_str(msg, ws_dev_info_strs[i].string, &infos[info_cnt].string);
1035 infos[info_cnt].index = ws_dev_info_strs[i].index;
1036 WDP_LOGD("%dth info [%d:%s]", i, infos[info_cnt].index, infos[info_cnt].string);
1042 WDP_LOGE("There is no item converted");
1047 edata = (wfd_oem_dev_data_s*) calloc(1, sizeof(wfd_oem_dev_data_s));
1049 WDP_LOGE("Failed to allocate memory for device information [%s]", strerror(errno));
1053 for (i = 0; i < info_cnt; i++) {
1054 switch (infos[i].index) {
1055 case WS_DEV_INFO_P2P_DEV_ADDR:
1056 res = _ws_txt_to_mac(infos[i].string, edata->p2p_dev_addr);
1058 memset(edata->p2p_dev_addr, 0x00, OEM_MACADDR_LEN);
1060 case WS_DEV_INFO_DEV_NAME:
1061 strncpy(edata->name, infos[i].string, OEM_DEV_NAME_LEN);
1062 edata->name[OEM_DEV_NAME_LEN] = '\0';
1064 case WS_DEV_INFO_DEV_TYPE:
1065 res = _ws_txt_to_devtype(infos[i].string, &edata->pri_dev_type, &edata->sec_dev_type);
1067 edata->pri_dev_type = 0;
1068 edata->sec_dev_type = 0;
1071 case WS_DEV_INFO_CONFIG_METHODS:
1072 config_methods = (int) strtoul(infos[i].string, NULL, 16);
1073 if (config_methods & WS_CONFIG_METHOD_DISPLAY)
1074 edata->config_methods |= WFD_OEM_WPS_MODE_DISPLAY;
1075 if (config_methods & WS_CONFIG_METHOD_PUSHBUTTON)
1076 edata->config_methods |= WFD_OEM_WPS_MODE_PBC;
1077 if (config_methods & WS_CONFIG_METHOD_KEYPAD)
1078 edata->config_methods |= WFD_OEM_WPS_MODE_KEYPAD;
1080 case WS_DEV_INFO_DEV_CAP:
1081 edata->dev_flags = (int) strtoul(infos[i].string, NULL, 16);
1083 case WS_DEV_INFO_GROUP_CAP:
1084 group_capab = (int) strtoul(infos[i].string, NULL, 16);
1085 if (group_capab & WS_GROUP_CAP_GROUP_OWNER) {
1086 edata->group_flags = WFD_OEM_GROUP_FLAG_GROUP_OWNER;
1087 edata->dev_role = WFD_OEM_DEV_ROLE_GO;
1089 if (group_capab & WS_GROUP_CAP_PERSISTENT_GROUP)
1090 edata->group_flags = WFD_OEM_GROUP_FLAG_PERSISTENT_GROUP;
1092 case WS_DEV_INFO_P2P_GO_ADDR:
1093 edata->dev_role = WFD_OEM_DEV_ROLE_GC;
1094 res = _ws_txt_to_mac(infos[i].string, edata->p2p_go_addr);
1096 memset(edata->p2p_go_addr, 0x00, OEM_MACADDR_LEN);
1099 WDP_LOGE("Unknown parameter [%d:%s]", infos[i].index, infos[i].string);
1102 if (infos[i].string)
1103 free(infos[i].string);
1106 __WDP_LOG_FUNC_EXIT__;
1110 static wfd_oem_conn_data_s *_convert_msg_to_conn_info(char *msg)
1112 __WDP_LOG_FUNC_ENTER__;
1115 ws_string_s infos[WS_CONN_INFO_LIMIT];
1116 wfd_oem_conn_data_s *edata = NULL;
1120 WDP_LOGE("Invalid parameter");
1123 WDP_LOGD("msg to convert [%s]", msg);
1125 memset(infos, 0x0, (WS_CONN_INFO_LIMIT) * sizeof(ws_string_s));
1126 for (i = 0; i < WS_CONN_INFO_LIMIT; i++) {
1127 res = _extract_value_str(msg, ws_conn_info_strs[i].string, &infos[info_cnt].string);
1129 infos[info_cnt].index = ws_conn_info_strs[i].index;
1135 WDP_LOGE("There is no item converted");
1140 edata = (wfd_oem_conn_data_s*) calloc(1, sizeof(wfd_oem_conn_data_s));
1142 WDP_LOGE("Failed to allocate memory for connection information [%s]", strerror(errno));
1146 for (i = 0; i < info_cnt; i++) {
1147 switch (infos[i].index) {
1148 case WS_CONN_INFO_DEV_PWD_ID:
1149 edata->dev_pwd_id = atoi(infos[i].string);
1151 case WS_CONN_INFO_STATUS:
1152 edata->status = atoi(infos[i].string);
1154 case WS_CONN_INFO_ERROR:
1155 edata->error = atoi(infos[i].string);
1158 WDP_LOGE("Unknown information [%d:%s]", infos[i].index, infos[i].string);
1161 if (infos[i].string)
1162 free(infos[i].string);
1165 __WDP_LOG_FUNC_EXIT__;
1169 static wfd_oem_invite_data_s *_convert_msg_to_invite_info(char *msg)
1171 __WDP_LOG_FUNC_ENTER__;
1174 ws_string_s infos[WS_INVITE_INFO_LIMIT];
1175 wfd_oem_invite_data_s *edata = NULL;
1179 WDP_LOGE("Invalid parameter");
1182 WDP_LOGD("msg to convert [%s]", msg);
1184 memset(infos, 0x0, (WS_INVITE_INFO_LIMIT) * sizeof(ws_string_s));
1185 for (i = 0; i < WS_INVITE_INFO_LIMIT; i++) {
1186 res = _extract_value_str(msg, ws_invite_info_strs[i].string, &infos[info_cnt].string);
1188 infos[info_cnt].index = ws_invite_info_strs[i].index;
1194 WDP_LOGE("There is no item converted");
1199 edata = (wfd_oem_invite_data_s*) calloc(1, sizeof(wfd_oem_invite_data_s));
1201 WDP_LOGE("Failed to allocate memory for invite information [%s]", strerror(errno));
1205 for (i = 0; i < info_cnt; i++) {
1206 switch (infos[i].index) {
1207 case WS_INVITE_INFO_GO_DEV_ADDR:
1208 res = _ws_txt_to_mac(infos[i].string, edata->go_dev_addr);
1210 memset(edata->go_dev_addr, 0x00, OEM_MACADDR_LEN);
1212 case WS_INVITE_INFO_BSSID:
1213 res = _ws_txt_to_mac(infos[i].string, edata->bssid);
1215 memset(edata->bssid, 0x00, OEM_MACADDR_LEN);
1217 case WS_INVITE_INFO_LISTEN:
1218 edata->listen = atoi(infos[i].string);
1220 case WS_INVITE_INFO_STATUS:
1221 edata->status = atoi(infos[i].string);
1224 WDP_LOGE("Unknown parameter [%d:%s]", infos[i].index, infos[i].string);
1227 if (infos[i].string)
1228 free(infos[i].string);
1231 __WDP_LOG_FUNC_EXIT__;
1235 static wfd_oem_group_data_s *_convert_msg_to_group_info(char *msg)
1237 __WDP_LOG_FUNC_ENTER__;
1240 ws_string_s infos[WS_GROUP_INFO_LIMIT];
1241 wfd_oem_group_data_s *edata = NULL;
1245 WDP_LOGE("Invalid parameter");
1248 WDP_LOGD("msg to convert [%s]", msg);
1250 memset(infos, 0x0, WS_GROUP_INFO_LIMIT * sizeof(ws_string_s));
1251 for (i = 0; i < WS_GROUP_INFO_LIMIT; i++) {
1252 res = _extract_value_str(msg, ws_group_info_strs[i].string, &infos[info_cnt].string);
1254 infos[info_cnt].index = ws_group_info_strs[i].index;
1260 WDP_LOGE("There is no item converted");
1265 edata = (wfd_oem_group_data_s*) calloc(1, sizeof(wfd_oem_group_data_s));
1267 WDP_LOGE("Failed to allocate memory for group information [%s]", strerror(errno));
1271 for (i = 0; i < info_cnt; i++) {
1272 switch (infos[i].index) {
1273 case WS_GROUP_INFO_SSID:
1274 strncpy(edata->ssid, infos[i].string, OEM_DEV_NAME_LEN);
1275 edata->ssid[OEM_DEV_NAME_LEN] = '\0';
1277 case WS_GROUP_INFO_FREQ:
1278 edata->freq = atoi(infos[i].string);
1280 case WS_GROUP_INFO_PASS:
1281 strncpy(edata->pass, infos[i].string, OEM_PASS_PHRASE_LEN);
1282 edata->pass[OEM_PASS_PHRASE_LEN] = '\0';
1284 case WS_GROUP_INFO_GO_DEV_ADDR:
1285 res = _ws_txt_to_mac(infos[i].string, edata->go_dev_addr);
1287 memset(edata->go_dev_addr, 0x00, OEM_MACADDR_LEN);
1290 WDP_LOGE("Unknown parameter [%d:%s]", infos[i].index, infos[i].string);
1293 if (infos[i].string)
1294 free(infos[i].string);
1297 __WDP_LOG_FUNC_EXIT__;
1301 static int _parsing_event_info(char *ifname, char *msg, wfd_oem_event_s *data)
1303 __WDP_LOG_FUNC_ENTER__;
1306 char *info_str = NULL;
1308 if (!msg || !data) {
1309 WDP_LOGE("Invalid parameter");
1310 __WDP_LOG_FUNC_EXIT__;
1313 WDP_LOGD("Event message [%s]", msg);
1315 // parsing event string
1316 for(i = 0; i < WS_EVENT_LIMIT; i++) {
1317 if (!strncmp(ws_event_strs[i].string, msg, strlen(ws_event_strs[i].string))) {
1322 WDP_LOGD("Event ID [%d]", i);
1324 if (i == WS_EVENT_LIMIT) {
1325 WDP_LOGE("Unknown event [%d]", i);
1329 // parsing event info
1330 info_str = msg + strlen(ws_event_strs[i].string) + 1;
1331 if (!strlen(info_str)) {
1332 WDP_LOGD("Nothing to parse anymore");
1333 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1334 __WDP_LOG_FUNC_EXIT__;
1338 switch (data->event_id) {
1339 case WS_EVENT_DEVICE_FOUND:
1341 _ws_txt_to_mac(info_str, data->dev_addr);
1342 info_str += OEM_MACSTR_LEN;
1344 wfd_oem_dev_data_s *edata = NULL;
1345 edata = _convert_msg_to_dev_info(info_str);
1347 WDP_LOGE("Failed to convert information string to device data");
1348 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1352 if (edata->dev_role == WFD_OEM_DEV_ROLE_GO) {
1353 memcpy(edata->p2p_intf_addr, data->dev_addr, OEM_MACADDR_LEN);
1354 memcpy(data->dev_addr, edata->p2p_dev_addr, OEM_MACADDR_LEN);
1356 data->edata_type = WFD_OEM_EDATA_TYPE_DEVICE;
1357 data->edata = (void*) edata;
1361 case WS_EVENT_PROV_DISC_PBC_REQ:
1362 case WS_EVENT_PROV_DISC_SHOW_PIN:
1363 case WS_EVENT_PROV_DISC_ENTER_PIN:
1364 case WS_EVENT_PROV_DISC_PBC_RESP:
1366 _ws_txt_to_mac(info_str, data->dev_addr);
1367 info_str += OEM_MACSTR_LEN;
1369 if (data->event_id == WS_EVENT_PROV_DISC_PBC_REQ) {
1370 data->wps_mode = WFD_OEM_WPS_MODE_PBC;
1371 } else if (data->event_id == WS_EVENT_PROV_DISC_ENTER_PIN) {
1372 data->wps_mode = WFD_OEM_WPS_MODE_KEYPAD;
1373 } else if (data->event_id == WS_EVENT_PROV_DISC_SHOW_PIN) {
1374 data->wps_mode = WFD_OEM_WPS_MODE_DISPLAY;
1375 strncpy(data->wps_pin, info_str, OEM_PINSTR_LEN);
1376 data->wps_pin[OEM_PINSTR_LEN] = '\0';
1377 info_str += OEM_PINSTR_LEN +1;
1380 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1384 case WS_EVENT_DEVICE_LOST:
1386 char *temp_mac = NULL;
1387 res = _extract_value_str(info_str, "p2p_dev_addr", &temp_mac);
1389 WDP_LOGE("Failed to extract device address");
1392 _ws_txt_to_mac(temp_mac, data->dev_addr);
1395 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1398 case WS_EVENT_FIND_STOPED:
1400 case WS_EVENT_GO_NEG_REQUEST:
1402 _ws_txt_to_mac(info_str, data->dev_addr);
1403 info_str += OEM_MACSTR_LEN;
1405 if (!strlen(info_str)) {
1406 WDP_LOGD("Nothing to parse anymore");
1407 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1411 wfd_oem_conn_data_s *edata = NULL;
1412 edata = _convert_msg_to_conn_info(info_str);
1414 WDP_LOGE("Failed to convert information string to connection data");
1415 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1418 data->edata_type = WFD_OEM_EDATA_TYPE_CONN;
1419 data->edata = (void*) edata;
1423 case WS_EVENT_PROV_DISC_FAILURE:
1424 case WS_EVENT_GO_NEG_FAILURE:
1425 case WS_EVENT_WPS_FAIL: // M_id(msg), error(config_error)
1427 case WS_EVENT_GROUP_FORMATION_FAILURE: // No incofmation sring
1428 case WS_EVENT_GO_NEG_SUCCESS:
1429 case WS_EVENT_WPS_SUCCESS:
1430 case WS_EVENT_GROUP_FORMATION_SUCCESS:
1431 /* No information string */
1432 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1434 case WS_EVENT_WPS_REG_SUCCESS: // "intf_addr"
1435 /* Interface address of peer will come up */
1437 case WS_EVENT_CONNECTED: // intf_addr(to)
1438 case WS_EVENT_DISCONNECTED:
1440 /* Interface address of connected peer will come up */
1441 char *temp_mac = NULL;
1442 res = _extract_value_str(info_str, "to", &temp_mac);
1444 WDP_LOGE("Failed to extract interface address");
1447 _ws_txt_to_mac(temp_mac, data->intf_addr);
1450 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1453 case WS_EVENT_STA_CONNECTED: // "intf_addr", dev_addr(dev_addr)
1454 case WS_EVENT_STA_DISCONNECTED:
1456 /* Interface address of connected peer will come up */
1457 _ws_txt_to_mac(info_str, data->intf_addr);
1459 char *temp_mac = NULL;
1460 res = _extract_value_str(info_str, "p2p_dev_addr", &temp_mac);
1462 WDP_LOGE("Failed to extract interface address");
1465 _ws_txt_to_mac(temp_mac, data->dev_addr);
1468 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1471 case WS_EVENT_INVITATION_RECEIVED:
1472 case WS_EVENT_INVITATION_RESULT:
1474 char *peer_addr_str = NULL;
1475 res = _extract_value_str(info_str, "sa", &peer_addr_str);
1476 if (res == 17/*(OEM_MACSTR_LEN-1)*/) {
1477 _ws_txt_to_mac(peer_addr_str, data->dev_addr);
1479 free(peer_addr_str);
1480 } else if (res < 0) {
1481 WDP_LOGE("Failed to extract source address");
1483 WDP_LOGE("Wrong source address");
1484 free(peer_addr_str);
1487 if (!strlen(info_str)) {
1488 WDP_LOGD("Nothing to parse anymore");
1489 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1493 wfd_oem_invite_data_s* edata = NULL;
1494 edata = _convert_msg_to_invite_info(info_str);
1496 WDP_LOGE("Failed to convert information string to invite data");
1497 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1501 data->edata_type = WFD_OEM_EDATA_TYPE_INVITE;
1502 data->edata = (void*) edata;
1506 case WS_EVENT_GROUP_STARTED:
1507 case WS_EVENT_GROUP_REMOVED:
1509 char *ifname_str = NULL;
1510 res = _extract_word(info_str, &ifname_str);
1512 WDP_LOGE("Failed to extract event param string");
1513 } else if (res == 0) {
1514 WDP_LOGE("Nothing extracted");
1519 WDP_LOGE("Parsing error(interface name)");
1522 strncpy(data->ifname, ifname_str, OEM_IFACE_NAME_LEN);
1523 data->ifname[OEM_IFACE_NAME_LEN] = '\0';
1525 info_str += strlen(ifname_str) + 1;
1530 char *dev_role_str = NULL;
1531 res = _extract_word(info_str, &dev_role_str);
1533 WDP_LOGE("Failed to extract event param string");
1534 } else if (res == 0) {
1535 WDP_LOGE("Nothing extracted");
1539 if (!dev_role_str) {
1540 WDP_LOGE("Parsing error(device role)");
1543 if (!strncmp(dev_role_str, "GO", 2))
1544 data->dev_role = WFD_OEM_DEV_ROLE_GO;
1545 else if (!strncmp(dev_role_str, "client", 6))
1546 data->dev_role = WFD_OEM_DEV_ROLE_GC;
1548 WDP_LOGE("Unknown device role [%s]", dev_role_str);
1550 info_str += strlen(dev_role_str) + 1;
1555 if (!strlen(info_str)) {
1556 WDP_LOGD("Nothing to parse anymore");
1557 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1561 wfd_oem_group_data_s* edata = NULL;
1562 edata= _convert_msg_to_group_info(info_str);
1564 WDP_LOGE("Failed to convert information string to group data");
1565 data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
1569 data->edata_type = WFD_OEM_EDATA_TYPE_GROUP;
1570 data->edata = (void*) edata;
1575 WDP_LOGE("Unknown event");
1579 __WDP_LOG_FUNC_EXIT__;
1583 static gboolean ws_event_handler(GIOChannel *source,
1584 GIOCondition condition,
1587 __WDP_LOG_FUNC_ENTER__;
1588 ws_sock_data_s * sd = (ws_sock_data_s*) data;
1589 char msg[1024] = {0, };
1592 wfd_oem_event_s *event = NULL;
1596 WDP_LOGE("Invalid parameter");
1597 // TODO: if error count is more than 10, disconnect this interface and reset sock data
1601 res = _ws_read_sock(sd->mon_sock, msg, sizeof(msg));
1603 WDP_LOGE("Failed to read socket. [%d]", sd->mon_sock);
1608 event = (wfd_oem_event_s*) calloc(1, sizeof(wfd_oem_event_s));
1610 WDP_LOGE("Failed to allocate memory for event. [%s]", strerror(errno));
1615 res = _parsing_event_info(sd->ifname, param, event);
1617 WDP_LOGE("Failed to parse event string");
1623 // This means event->event_data is NULL
1626 switch (event->event_id) {
1627 case WS_EVENT_DEVICE_FOUND:
1628 event_id = WFD_OEM_EVENT_PEER_FOUND;
1630 case WS_EVENT_DEVICE_LOST:
1631 event_id = WFD_OEM_EVENT_PEER_DISAPPEARED;
1633 case WS_EVENT_FIND_STOPED:
1634 event_id = WFD_OEM_EVENT_DISCOVERY_FINISHED;
1636 case WS_EVENT_PROV_DISC_PBC_REQ:
1637 event_id = WFD_OEM_EVENT_PROV_DISC_REQ;
1639 case WS_EVENT_PROV_DISC_PBC_RESP:
1640 event_id = WFD_OEM_EVENT_PROV_DISC_RESP;
1642 case WS_EVENT_PROV_DISC_SHOW_PIN:
1643 event_id = WFD_OEM_EVENT_PROV_DISC_DISPLAY;
1645 case WS_EVENT_PROV_DISC_ENTER_PIN:
1646 event_id = WFD_OEM_EVENT_PROV_DISC_KEYPAD;
1648 case WS_EVENT_GO_NEG_REQUEST:
1649 event_id = WFD_OEM_EVENT_GO_NEG_REQ;
1651 case WS_EVENT_GO_NEG_FAILURE:
1652 event_id = WFD_OEM_EVENT_GO_NEG_FAIL;
1656 case WS_EVENT_GO_NEG_SUCCESS:
1657 event_id = WFD_OEM_EVENT_GO_NEG_DONE;
1659 case WS_EVENT_WPS_FAIL:
1660 case WS_EVENT_GROUP_FORMATION_FAILURE:
1661 event_id = WFD_OEM_EVENT_WPS_FAIL;
1663 case WS_EVENT_WPS_SUCCESS:
1664 case WS_EVENT_WPS_REG_SUCCESS:
1665 case WS_EVENT_GROUP_FORMATION_SUCCESS:
1666 event_id = WFD_OEM_EVENT_WPS_DONE;
1667 // TODO: connect to supplicant via group interface
1669 case WS_EVENT_CONNECTED:
1671 unsigned char null_mac[OEM_MACADDR_LEN] = {0, 0, 0, 0, 0, 0};
1672 if (!memcmp(event->intf_addr, null_mac, OEM_MACADDR_LEN))
1674 event_id = WFD_OEM_EVENT_CONNECTED;
1677 case WS_EVENT_STA_CONNECTED:
1678 event_id = WFD_OEM_EVENT_STA_CONNECTED;
1680 case WS_EVENT_GROUP_STARTED:
1681 event_id = WFD_OEM_EVENT_GROUP_CREATED;
1682 res = _connect_to_supplicant(GROUP_IFACE_NAME, &g_pd->group);
1684 WDP_LOGE("Failed to connect to group interface of supplicant");
1688 case WS_EVENT_GROUP_REMOVED:
1689 event_id = WFD_OEM_EVENT_GROUP_DESTROYED;
1691 res = _disconnect_from_supplicant(GROUP_IFACE_NAME, g_pd->group);
1693 WDP_LOGE("Failed to disconnect from group interface of supplicant");
1699 case WS_EVENT_INVITATION_RECEIVED:
1701 wfd_oem_invite_data_s* edata = NULL;
1702 edata = (wfd_oem_invite_data_s*) event->edata;
1703 event_id = WFD_OEM_EVENT_INVITATION_REQ;
1706 case WS_EVENT_INVITATION_RESULT:
1707 event_id = WFD_OEM_EVENT_INVITATION_RES;
1709 case WS_EVENT_DISCONNECTED:
1710 event_id = WFD_OEM_EVENT_DISCONNECTED;
1712 case WS_EVENT_STA_DISCONNECTED:
1713 event_id = WFD_OEM_EVENT_STA_DISCONNECTED;
1715 case WS_EVENT_TERMINATING:
1716 event_id = WFD_OEM_EVENT_TERMINATING;
1719 WDP_LOGD("Unknown event [%d]", event->event_id);
1723 event->event_id = event_id;
1724 g_pd->callback(g_pd->user_data, event);
1731 __WDP_LOG_FUNC_EXIT__;
1735 static int _ws_reset_plugin(ws_plugin_data_s *pd)
1737 __WDP_LOG_FUNC_ENTER__;
1740 WDP_LOGE("Invalid parameter");
1741 __WDP_LOG_FUNC_EXIT__;
1750 __WDP_LOG_FUNC_EXIT__;
1754 int ws_init(wfd_oem_event_cb callback, void *user_data)
1756 __WDP_LOG_FUNC_ENTER__;
1759 _ws_reset_plugin(g_pd);
1762 g_pd = (ws_plugin_data_s*) calloc(1, sizeof(ws_plugin_data_s));
1764 WDP_LOGE("Failed to allocate memory for plugin data. [%s]", strerror(errno));
1768 g_pd->callback = callback;
1769 g_pd->user_data = user_data;
1770 g_pd->initialized = TRUE;
1772 __WDP_LOG_FUNC_EXIT__;
1778 __WDP_LOG_FUNC_ENTER__;
1781 _ws_reset_plugin(g_pd);
1785 __WDP_LOG_FUNC_EXIT__;
1791 __WDP_LOG_FUNC_ENTER__;
1792 int global_sock = -1;
1794 char cmd[128] = {0, };
1795 char reply[1024] = {0, };
1797 /* load wlan driver and wpa_supplicant */
1798 system("/usr/bin/wlan.sh p2p");
1799 system("/usr/sbin/p2p_supp.sh start");
1801 global_sock = _create_ctrl_intf(GLOBAL_INTF_PATH, SUPPL_GLOBAL_INTF_PATH);
1802 if (global_sock < SOCK_FD_MIN) {
1803 WDP_LOGE("Failed to create global socket");
1804 __WDP_LOG_FUNC_EXIT__;
1807 WDP_LOGD("Succeeded to create global socket. [%d]", global_sock);
1809 res = _ws_send_cmd(global_sock, WS_CMD_INTERFACES, reply, sizeof(reply));
1811 WDP_LOGE("Failed to send command to wpa_supplicant");
1812 __WDP_LOG_FUNC_EXIT__;
1816 if (!strstr(reply, COMMON_IFACE_NAME)){
1817 memset(cmd, 0x0, 128);
1818 memset(reply, 0x0, 1024);
1820 snprintf(cmd, sizeof(cmd), WS_CMD_INTERFACE_ADD "%s%s",
1821 COMMON_IFACE_NAME, "\t/usr/etc/wifi-direct/p2p_supp.conf\tnl80211\t/var/run/wpa_supplicant");
1822 res = _ws_send_cmd(global_sock, cmd, reply, sizeof(reply));
1824 WDP_LOGE("Failed to send command to wpa_supplicant");
1826 system("/usr/sbin/p2p_supp.sh stop");
1827 system("/usr/bin/wlan.sh stop");
1828 __WDP_LOG_FUNC_EXIT__;
1832 if (strstr(reply, "FAIL")) {
1833 WDP_LOGE("Failed to create %s interface", COMMON_IFACE_NAME);
1835 system("/usr/sbin/p2p_supp.sh stop");
1836 system("/usr/bin/wlan.sh stop");
1837 __WDP_LOG_FUNC_EXIT__;
1840 WDP_LOGD("Succeeded to create %s interface", COMMON_IFACE_NAME);
1842 WDP_LOGD("%s interface exist", COMMON_IFACE_NAME);
1844 res = _connect_to_supplicant(COMMON_IFACE_NAME, &g_pd->common);
1847 system("/usr/sbin/p2p_supp.sh stop");
1848 system("/usr/bin/wlan.sh stop");
1849 __WDP_LOG_FUNC_EXIT__;
1853 g_pd->global_sock = global_sock;
1854 g_pd->activated = TRUE;
1856 __WDP_LOG_FUNC_EXIT__;
1862 __WDP_LOG_FUNC_ENTER__;
1863 char cmd[32] = {0, };
1864 char reply[1024]={0,};
1866 char ifname[OEM_IFACE_NAME_LEN];
1868 if (!g_pd->activated) {
1869 WDP_LOGE("Wi-Fi Direct is not activated");
1874 _disconnect_from_supplicant(GROUP_IFACE_NAME, g_pd->group);
1878 res = _disconnect_from_supplicant("wlan0", g_pd->common);
1880 WDP_LOGE("Failed to disconnect common interface(%s) from supplicant. ", ifname);
1881 g_pd->common = NULL;
1883 // terminate wpasupplicant
1884 snprintf(cmd, sizeof(cmd), WS_CMD_TERMINATE);
1885 res = _ws_send_cmd(g_pd->global_sock, cmd, reply, sizeof(reply));
1887 WDP_LOGE("Failed to send command to wpa_supplicant");
1888 system("/usr/sbin/p2p_supp.sh stop");
1892 if (!strncmp(reply, "FAIL", 4)) {
1893 WDP_LOGE("Failed to terminate wpa_supplicant");
1894 system("/usr/sbin/p2p_supp.sh stop");
1898 unlink(GLOBAL_INTF_PATH);
1899 if (g_pd->global_sock >= SOCK_FD_MIN)
1900 close(g_pd->global_sock);
1901 g_pd->global_sock = -1;
1903 system("/usr/bin/wlan.sh stop");
1904 g_pd->activated = FALSE;
1906 __WDP_LOG_FUNC_EXIT__;
1910 int ws_start_scan(wfd_oem_scan_param_s *param)
1912 __WDP_LOG_FUNC_ENTER__;
1913 ws_sock_data_s *sock = g_pd->common;
1914 char cmd[32] = {0, };
1915 char reply[1024] = {0, };
1916 char time_str[4] = {0, };
1920 WDP_LOGE("Invalid parameter");
1925 WDP_LOGE("Socket is NULL");
1932 if (param->scan_time)
1933 snprintf(time_str, 4, " %d", param->scan_time);
1935 if (param->scan_mode == WFD_OEM_SCAN_MODE_ACTIVE)
1936 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_FIND "%s", (param->scan_time > 0) ? time_str : "");
1938 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_LISTEN);
1940 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
1942 WDP_LOGE("Failed to send command to wpa_supplicant");
1943 __WDP_LOG_FUNC_EXIT__;
1947 if (strstr(reply, "FAIL")) {
1948 WDP_LOGE("Failed to start scan");
1949 __WDP_LOG_FUNC_EXIT__;
1952 WDP_LOGD("Succeeded to start scan");
1954 __WDP_LOG_FUNC_EXIT__;
1958 int ws_restart_scan(int freq)
1960 __WDP_LOG_FUNC_ENTER__;
1961 ws_sock_data_s *sock = g_pd->common;
1962 char cmd[32] = {0, };
1963 char reply[1024] = {0, };
1967 WDP_LOGE("Socket is NULL");
1972 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_FIND " 2 freq=%d", freq);
1974 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_FIND " 2");
1976 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
1978 WDP_LOGE("Failed to send command to wpa_supplicant");
1979 __WDP_LOG_FUNC_EXIT__;
1983 if (strstr(reply, "FAIL")) {
1984 WDP_LOGE("Failed to start scan");
1985 __WDP_LOG_FUNC_EXIT__;
1988 WDP_LOGD("Succeeded to start scan");
1990 __WDP_LOG_FUNC_EXIT__;
1996 __WDP_LOG_FUNC_ENTER__;
1997 ws_sock_data_s *sock = g_pd->common;
1998 char reply[1024] = {0, };
2002 WDP_LOGE("Socket is NULL");
2006 res = _ws_send_cmd(sock->ctrl_sock, WS_CMD_P2P_STOP_FIND, reply, sizeof(reply));
2008 WDP_LOGE("Failed to send command to wpa_supplicant");
2009 __WDP_LOG_FUNC_EXIT__;
2013 if (strstr(reply, "FAIL")) {
2014 WDP_LOGE("Failed to stop scan");
2015 __WDP_LOG_FUNC_EXIT__;
2018 WDP_LOGD("Succeeded to stop scan");
2021 __WDP_LOG_FUNC_EXIT__;
2025 int ws_get_visibility(int *visibility)
2027 __WDP_LOG_FUNC_ENTER__;
2029 __WDP_LOG_FUNC_EXIT__;
2033 int ws_set_visibility(int visibility)
2035 __WDP_LOG_FUNC_ENTER__;
2037 __WDP_LOG_FUNC_EXIT__;
2041 int ws_get_scan_result(GList **peers, int *peer_count)
2043 __WDP_LOG_FUNC_ENTER__;
2044 ws_sock_data_s *sock = g_pd->common;
2045 char cmd[32] = {0, };
2046 char reply[1024] = {0,};
2047 wfd_oem_device_s *peer = NULL;
2050 if (!peers || !peer_count) {
2051 WDP_LOGE("Invalid parameter");
2056 WDP_LOGE("Socket is NULL");
2060 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_PEER_FIRST);
2061 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2063 WDP_LOGE("Failed to send command to wpa_supplicant");
2064 __WDP_LOG_FUNC_EXIT__;
2068 if (strstr(reply, "FAIL")) {
2069 WDP_LOGE("Failed to get first peer info");
2070 __WDP_LOG_FUNC_EXIT__;
2073 WDP_LOGD("Succeeded to get first peer info");
2075 peer = (wfd_oem_device_s *) calloc(1, sizeof(wfd_oem_device_s));
2077 res = _parsing_peer_info(reply, peer);
2079 WDP_LOGE("Failed to parsing peer info");
2081 __WDP_LOG_FUNC_EXIT__;
2085 *peers = g_list_prepend(*peers, peer);
2088 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_PEER_NEXT MACSTR, MAC2STR(peer->dev_addr));
2089 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2091 WDP_LOGE("Failed to send command to wpa_supplicant");
2095 if (strstr(reply, "FAIL")) {
2096 WDP_LOGE("Failed to get first peer info");
2099 WDP_LOGD("Succeeded to get first peer info");
2101 peer = (wfd_oem_device_s *) calloc(1, sizeof(wfd_oem_device_s));
2103 res = _parsing_peer_info(reply, peer);
2105 WDP_LOGE("Failed to parsing peer info");
2110 *peers = g_list_prepend(*peers, peer);
2113 __WDP_LOG_FUNC_EXIT__;
2117 int ws_get_peer_info(unsigned char *peer_addr, wfd_oem_device_s **peer)
2119 __WDP_LOG_FUNC_ENTER__;
2120 ws_sock_data_s *sock = g_pd->common;
2121 char cmd[32] = {0, };
2122 char reply[1024] = {0,};
2123 wfd_oem_device_s *ws_dev = NULL;
2126 if (!peer_addr || !peer) {
2127 WDP_LOGE("Invalid parameter");
2132 WDP_LOGE("Socket is NULL");
2136 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_PEER MACSTR, MAC2STR(peer_addr));
2137 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2139 WDP_LOGE("Failed to send command to wpa_supplicant");
2140 __WDP_LOG_FUNC_EXIT__;
2144 if (strstr(reply, "FAIL")) {
2145 WDP_LOGE("Failed to get peer info [" MACSTR "]", MAC2STR(peer_addr));
2146 __WDP_LOG_FUNC_EXIT__;
2149 WDP_LOGD("Succeeded to get peer info [" MACSTR "]", MAC2STR(peer_addr));
2151 ws_dev = (wfd_oem_device_s*) calloc(1, sizeof(wfd_oem_device_s));
2153 // TODO: parsing peer info
2154 res = _parsing_peer_info(reply, ws_dev);
2156 WDP_LOGE("Failed to parsing peer info");
2158 __WDP_LOG_FUNC_EXIT__;
2163 __WDP_LOG_FUNC_EXIT__;
2167 int ws_prov_disc_req(unsigned char *peer_addr, wfd_oem_wps_mode_e wps_mode, int join)
2169 __WDP_LOG_FUNC_ENTER__;
2170 ws_sock_data_s *sock = g_pd->common;
2171 char cmd[64] = {0, };
2172 char reply[1024]={0,};
2176 WDP_LOGE("Socket is NULL");
2181 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_PROV_DISC MACSTR "%s",
2182 MAC2STR(peer_addr), _ws_wps_to_txt(wps_mode));
2185 strncat(cmd, WS_STR_JOIN, 5);
2187 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2189 WDP_LOGE("Failed to send command to wpa_supplicant");
2190 __WDP_LOG_FUNC_EXIT__;
2194 if (strstr(reply, "FAIL")) {
2195 WDP_LOGE("Failed to send provision discovery to peer[" MACSTR "]", MAC2STR(peer_addr));
2196 __WDP_LOG_FUNC_EXIT__;
2199 WDP_LOGD("Succeeded to send provision discovery to peer[" MACSTR "]", MAC2STR(peer_addr));
2201 __WDP_LOG_FUNC_EXIT__;
2205 int ws_connect(unsigned char *peer_addr, wfd_oem_conn_param_s *param)
2207 __WDP_LOG_FUNC_ENTER__;
2208 ws_sock_data_s *sock = g_pd->common;
2209 char cmd[64] = {0, };
2210 char reply[1024] = {0, };
2214 WDP_LOGE("Invalid parameter");
2219 WDP_LOGE("Socket is NULL");
2223 if (param->wps_pin[0] != '\0')
2224 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_CONNECT MACSTR " %s%s" ,
2225 MAC2STR(peer_addr), param->wps_pin,
2226 _ws_wps_to_txt(param->wps_mode));
2228 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_CONNECT MACSTR "%s",
2230 _ws_wps_to_txt(param->wps_mode));
2232 if (param->conn_flags & WFD_OEM_CONN_TYPE_JOIN)
2233 strncat(cmd, WS_STR_JOIN, 5);
2234 else if (param->conn_flags& WFD_OEM_CONN_TYPE_AUTH)
2235 strncat(cmd, WS_STR_AUTH, 5);
2237 if (param->conn_flags & WFD_OEM_CONN_TYPE_PERSISTENT)
2238 strncat(cmd, WS_STR_PERSISTENT, 11);
2240 WDP_LOGI("Connection command [%s]", cmd);
2242 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2244 WDP_LOGE("Failed to send command to wpa_supplicant");
2245 __WDP_LOG_FUNC_EXIT__;
2249 if (strstr(reply, "FAIL")) {
2250 WDP_LOGE("Failed to connect with peer[" MACSTR "]", MAC2STR(peer_addr));
2251 __WDP_LOG_FUNC_EXIT__;
2254 WDP_LOGD("Succeeded to send connection command to peer[" MACSTR "]", MAC2STR(peer_addr));
2256 __WDP_LOG_FUNC_EXIT__;
2260 int ws_disconnect(unsigned char *peer_addr)
2262 __WDP_LOG_FUNC_ENTER__;
2263 ws_sock_data_s *sock = g_pd->common;
2264 char cmd[32] = {0, };
2265 char reply[1024]={0,};
2268 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_GROUP_REMOVE "%s", GROUP_IFACE_NAME);
2269 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2271 WDP_LOGE("Failed to send command to wpa_supplicant");
2272 __WDP_LOG_FUNC_EXIT__;
2276 if (strstr(reply, "FAIL")) {
2277 WDP_LOGE("Failed to disconnect with peer[" MACSTR "]", MAC2STR(peer_addr));
2278 __WDP_LOG_FUNC_EXIT__;
2281 WDP_LOGD("Succeeded to send disconnection command to peer[" MACSTR "]", MAC2STR(peer_addr));
2283 __WDP_LOG_FUNC_EXIT__;
2287 int ws_reject_connection(unsigned char *peer_addr)
2289 __WDP_LOG_FUNC_ENTER__;
2290 ws_sock_data_s *sock = g_pd->common;
2291 char cmd[40] = {0, };
2292 char reply[1024]={0,};
2296 WDP_LOGE("Socket is NULL");
2300 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_REJECT MACSTR, MAC2STR(peer_addr));
2301 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2303 WDP_LOGE("Failed to send command to wpa_supplicant");
2304 __WDP_LOG_FUNC_EXIT__;
2308 if (strstr(reply, "FAIL")) {
2309 WDP_LOGE("Failed to reject connection with peer[" MACSTR "]", MAC2STR(peer_addr));
2310 __WDP_LOG_FUNC_EXIT__;
2313 WDP_LOGD("Succeeded to send reject connection command to peer[" MACSTR "]", MAC2STR(peer_addr));
2315 __WDP_LOG_FUNC_EXIT__;
2319 int ws_cancel_connection(unsigned char *peer_addr)
2321 __WDP_LOG_FUNC_ENTER__;
2325 __WDP_LOG_FUNC_EXIT__;
2329 int ws_get_connected_peers(GList **peers, int *peer_count)
2331 __WDP_LOG_FUNC_ENTER__;
2333 __WDP_LOG_FUNC_EXIT__;
2337 int ws_get_pin(char *pin)
2339 __WDP_LOG_FUNC_ENTER__;
2341 __WDP_LOG_FUNC_EXIT__;
2345 int ws_set_pin(char *pin)
2347 __WDP_LOG_FUNC_ENTER__;
2349 __WDP_LOG_FUNC_EXIT__;
2353 int ws_get_supported_wps_mode()
2355 __WDP_LOG_FUNC_ENTER__;
2357 __WDP_LOG_FUNC_EXIT__;
2361 int ws_create_group(int persistent, int freq)
2363 __WDP_LOG_FUNC_ENTER__;
2364 ws_sock_data_s *sock = g_pd->common;
2365 char cmd[44] = {0, };
2366 char reply[1024]={0,};
2370 WDP_LOGE("Socket is NULL");
2375 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_GROUP_ADD WS_STR_PERSISTENT);
2377 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_GROUP_ADD WS_STR_FREQ_2G);
2379 // TODO: add frequency option
2381 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2383 WDP_LOGE("Failed to send command to wpa_supplicant");
2384 __WDP_LOG_FUNC_EXIT__;
2388 if (strstr(reply, "FAIL")) {
2389 WDP_LOGE("Failed to add group");
2390 __WDP_LOG_FUNC_EXIT__;
2393 WDP_LOGD("Succeeded to add group");
2395 __WDP_LOG_FUNC_EXIT__;
2399 int ws_destroy_group(const char *ifname)
2401 __WDP_LOG_FUNC_ENTER__;
2402 ws_sock_data_s *sock = g_pd->common;
2403 char cmd[32] = {0, };
2404 char reply[1024]={0,};
2408 WDP_LOGE("Invalid parameter");
2413 WDP_LOGE("Socket is NULL");
2417 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_GROUP_REMOVE "%s", ifname);
2419 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2421 WDP_LOGE("Failed to send command to wpa_supplicant");
2422 __WDP_LOG_FUNC_EXIT__;
2426 if (strstr(reply, "FAIL")) {
2427 WDP_LOGE("Failed to remove group");
2428 __WDP_LOG_FUNC_EXIT__;
2431 WDP_LOGD("Succeeded to remove group");
2435 __WDP_LOG_FUNC_EXIT__;
2439 int ws_invite(unsigned char *peer_addr, wfd_oem_invite_param_s *param)
2441 __WDP_LOG_FUNC_ENTER__;
2442 ws_sock_data_s *sock = g_pd->group;
2443 char cmd[128] = {0, };
2444 char reply[1024]={0,};
2447 if (!peer_addr || !param) {
2448 WDP_LOGE("Invalid parameter");
2453 WDP_LOGE("Group interface not connected");
2457 WDP_LOGD("Invite: Peer[" MACSTR "], GO Addr[" MACSTR "]", MAC2STR(peer_addr), MAC2STR(param->go_dev_addr));
2460 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_INVITE "persistent=%d peer=" MACSTR " go_dev_addr=" MACSTR,
2461 param->net_id, MAC2STR(peer_addr),
2462 MAC2STR(param->go_dev_addr));
2464 snprintf(cmd, sizeof(cmd), WS_CMD_P2P_INVITE "group=%s peer=" MACSTR " go_dev_addr=" MACSTR,
2465 param->ifname, MAC2STR(peer_addr),
2466 MAC2STR(param->go_dev_addr));
2468 res = _ws_send_cmd(sock->ctrl_sock, cmd, reply, sizeof(reply));
2470 WDP_LOGE("Failed to send command to wpa_supplicant");
2471 __WDP_LOG_FUNC_EXIT__;
2475 if (strstr(reply, "FAIL")) {
2476 WDP_LOGE("Failed to invite peer");
2477 __WDP_LOG_FUNC_EXIT__;
2480 WDP_LOGD("Succeeded to invite peer");
2482 __WDP_LOG_FUNC_EXIT__;
2486 // Only group owner can use this command
2487 int ws_wps_start(unsigned char *peer_addr, int wps_mode, const char *pin)
2489 __WDP_LOG_FUNC_ENTER__;
2490 ws_sock_data_s *sock = g_pd->group;
2491 char cmd[40] = {0, };
2492 char reply[1024]={0,};
2495 if (!peer_addr || !pin) {
2496 WDP_LOGE("Invalid parameter");
2501 WDP_LOGE("Group interface not connected");
2505 if (wps_mode == WFD_OEM_WPS_MODE_PBC)
2506 snprintf(cmd, sizeof(cmd), WS_CMD_WPS_PBC "p2p_dev_addr=" MACSTR, MAC2STR(peer_addr));
2508 snprintf(cmd, sizeof(cmd), WS_CMD_WPS_PIN MACSTR " %s", MAC2STR(peer_addr), pin);
2510 res = _ws_send_cmd(sock->ctrl_sock, cmd,reply, sizeof(reply));
2512 WDP_LOGE("Failed to send command to wpa_supplicant");
2513 __WDP_LOG_FUNC_EXIT__;
2517 if (strstr(reply, "FAIL")) {
2518 WDP_LOGE("Failed to start WPS");
2519 __WDP_LOG_FUNC_EXIT__;
2522 WDP_LOGD("Succeeded to start WPS");
2524 __WDP_LOG_FUNC_EXIT__;
2528 int ws_enrollee_start(unsigned char *peer_addr, int wps_mode, const char *pin)
2530 __WDP_LOG_FUNC_ENTER__;
2531 ws_sock_data_s *sock = g_pd->common;
2532 char cmd[64] = {0, };
2533 char reply[1024]={0,};
2536 if (!peer_addr || !pin) {
2537 WDP_LOGE("Invalid parameter");
2542 WDP_LOGE("Socket is NULL");
2546 if (wps_mode == WFD_OEM_WPS_MODE_PBC)
2547 snprintf(cmd, sizeof(cmd), WS_CMD_WPS_ENROLLEE MACSTR "%s",
2548 MAC2STR(peer_addr), _ws_wps_to_txt(wps_mode));
2550 snprintf(cmd, sizeof(cmd), WS_CMD_WPS_ENROLLEE MACSTR " %s%s",
2551 MAC2STR(peer_addr), pin, _ws_wps_to_txt(wps_mode));
2553 res = _ws_send_cmd(sock->ctrl_sock, cmd,reply, sizeof(reply));
2555 WDP_LOGE("Failed to send command to wpa_supplicant");
2556 __WDP_LOG_FUNC_EXIT__;
2560 if (strstr(reply, "FAIL")) {
2561 WDP_LOGE("Failed to start WPS");
2562 __WDP_LOG_FUNC_EXIT__;
2565 WDP_LOGD("Succeeded to start WPS");
2567 __WDP_LOG_FUNC_EXIT__;
2573 __WDP_LOG_FUNC_ENTER__;
2574 ws_sock_data_s *sock = g_pd->common;
2575 char reply[1024]={0,};
2579 WDP_LOGE("Socket is NULL");
2583 res = _ws_send_cmd(sock->ctrl_sock, WS_CMD_WPS_CANCEL, reply, sizeof(reply));
2585 WDP_LOGE("Failed to send command to wpa_supplicant");
2586 __WDP_LOG_FUNC_EXIT__;
2590 if (strstr(reply, "FAIL")) {
2591 WDP_LOGE("Failed to cancel WPS");
2592 __WDP_LOG_FUNC_EXIT__;
2595 WDP_LOGD("Succeeded to cancel WPS");
2597 __WDP_LOG_FUNC_EXIT__;
2601 int ws_get_dev_name(char *dev_name)
2603 __WDP_LOG_FUNC_ENTER__;
2605 __WDP_LOG_FUNC_EXIT__;
2609 int ws_set_dev_name(char *dev_name)
2611 __WDP_LOG_FUNC_ENTER__;
2612 ws_sock_data_s *sock = g_pd->common;
2613 char cmd[128] = {0, };
2614 char reply[1024]={0,};
2617 if (!dev_name || !strlen(dev_name)) {
2618 WDP_LOGE( "Invalid parameter");
2619 __WDP_LOG_FUNC_EXIT__;
2624 WDP_LOGE("Socket is NULL");
2628 snprintf(cmd, sizeof(cmd), WS_CMD_SET "device_name %s", dev_name);
2629 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2631 WDP_LOGE("Failed to send command to wpa_supplicant");
2632 __WDP_LOG_FUNC_EXIT__;
2636 if (strstr(reply, "FAIL")) {
2637 WDP_LOGE("Failed to set device name");
2638 __WDP_LOG_FUNC_EXIT__;
2641 WDP_LOGD("Succeeded to set device name");
2643 memset(cmd, 0x0, 128);
2644 memset(reply, 0x0, 1024);
2646 snprintf(cmd, sizeof(cmd), WS_CMD_SET "p2p_ssid_postfix %s", dev_name);
2647 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2649 WDP_LOGE("Failed to send command to wpa_supplicant");
2650 __WDP_LOG_FUNC_EXIT__;
2654 if (strstr(reply, "FAIL")) {
2655 WDP_LOGE("Failed to set SSID postfix");
2656 __WDP_LOG_FUNC_EXIT__;
2659 WDP_LOGD("Succeeded to set SSID postfix");
2661 __WDP_LOG_FUNC_EXIT__;
2665 int ws_get_dev_mac(char *dev_mac)
2667 __WDP_LOG_FUNC_ENTER__;
2669 __WDP_LOG_FUNC_EXIT__;
2673 int ws_get_dev_type(int *pri_dev_type, int *sec_dev_type)
2675 __WDP_LOG_FUNC_ENTER__;
2677 __WDP_LOG_FUNC_EXIT__;
2681 int ws_set_dev_type(int pri_dev_type, int sec_dev_type)
2683 __WDP_LOG_FUNC_ENTER__;
2685 __WDP_LOG_FUNC_EXIT__;
2689 int ws_get_go_intent(int *go_intent)
2691 __WDP_LOG_FUNC_ENTER__;
2692 ws_sock_data_s *sock = g_pd->common;
2693 char cmd[80] = {0, };
2694 char reply[1024]={0,};
2698 WDP_LOGE("Socket is NULL");
2702 if (go_intent == NULL)
2704 WDP_LOGE("p2p_go_intent is NULL");
2705 __WDP_LOG_FUNC_EXIT__;
2709 snprintf(cmd, sizeof(cmd), WS_CMD_GET "p2p_go_intent");
2710 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2712 WDP_LOGE("Failed to send command to wpa_supplicant");
2713 __WDP_LOG_FUNC_EXIT__;
2717 if (strstr(reply, "FAIL")) {
2718 WDP_LOGE("Failed to set go intent");
2719 __WDP_LOG_FUNC_EXIT__;
2723 *go_intent = atoi(reply);
2724 WDP_LOGD("Succeeded to get go intent(%d)", *go_intent);
2726 __WDP_LOG_FUNC_EXIT__;
2730 int ws_set_go_intent(int go_intent)
2732 __WDP_LOG_FUNC_ENTER__;
2733 ws_sock_data_s *sock = g_pd->common;
2734 char cmd[80] = {0, };
2735 char reply[1024]={0,};
2739 WDP_LOGE("Socket is NULL");
2743 snprintf(cmd, sizeof(cmd), WS_CMD_SET "p2p_go_intent %d", go_intent);
2745 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2747 WDP_LOGE("Failed to send command to wpa_supplicant");
2748 __WDP_LOG_FUNC_EXIT__;
2752 if (strstr(reply, "FAIL")) {
2753 WDP_LOGE("Failed to set go intent");
2754 __WDP_LOG_FUNC_EXIT__;
2757 WDP_LOGD("Succeeded to set go intent(%d)", go_intent);
2759 __WDP_LOG_FUNC_EXIT__;
2763 int _parsing_networks(char* buf, ws_network_info_s networks[], int *network_cnt)
2765 __WDP_LOG_FUNC_ENTER__;
2768 char *tmp_str = NULL;
2771 // Passing first line : "network id / ssid / bssid / flags"
2772 while (*ptr != '\n') {
2778 while(*ptr != '\0') {
2779 res = _extract_word(ptr, &tmp_str);
2781 networks[count].network_id = atoi(tmp_str);
2788 res = _extract_word(ptr, &tmp_str);
2790 snprintf(networks[count].ssid, WS_SSID_LEN, tmp_str);
2797 res = _extract_word(ptr, &tmp_str);
2799 _ws_txt_to_mac(tmp_str, networks[count].bssid);
2806 res = _extract_word(ptr, &tmp_str);
2808 if (strstr(tmp_str, "CURRENT"))
2809 networks[count].flags |= WFD_OEM_NETFLAG_CURRENT;
2810 if (strstr(tmp_str, "DISABLED"))
2811 networks[count].flags |= WFD_OEM_NETFLAG_DISABLED;
2812 if (strstr(tmp_str, "TEMP-DISABLED"))
2813 networks[count].flags |= WFD_OEM_NETFLAG_TEMP_DISABLED;
2814 if (strstr(tmp_str, "P2P-PERSISTENT"))
2815 networks[count].flags |= WFD_OEM_NETFLAG_P2P_PERSISTENT;
2825 *network_cnt = count;
2827 __WDP_LOG_FUNC_EXIT__;
2831 int ws_get_persistent_groups(wfd_oem_persistent_group_s **groups, int *group_count)
2833 __WDP_LOG_FUNC_ENTER__;
2834 ws_sock_data_s *sock = g_pd->common;
2835 char cmd[80] = {0, };
2836 char reply[1024]={0,};
2837 ws_network_info_s networks[WS_MAX_PERSISTENT_COUNT];
2838 wfd_oem_persistent_group_s *wfd_persistent_groups = NULL;
2842 if (!groups || !group_count) {
2843 WDP_LOGE("Invalid parameter");
2848 WDP_LOGE("Socket is NULL");
2852 memset(networks, 0, (sizeof(ws_network_info_s) * WS_MAX_PERSISTENT_COUNT));
2854 /* Reading lists the configured networks, including stored information for persistent groups.
2855 The identifier in this is used with p2p_group_add and p2p_invite to indicate witch persistent
2856 group is to be reinvoked. */
2857 snprintf(cmd, sizeof(cmd), WS_CMD_LIST_NETWORKS);
2858 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2860 WDP_LOGE("Failed to send command to wpa_supplicant");
2861 __WDP_LOG_FUNC_EXIT__;
2865 if (strstr(reply, "FAIL")) {
2866 WDP_LOGE("Failed to get list of networks");
2867 __WDP_LOG_FUNC_EXIT__;
2870 WDP_LOGD("Succeeded to get list of networks");
2872 _parsing_networks(reply, networks, &cnt);
2873 WDP_LOGD("Persistent Group Count=%d", cnt);
2874 if (cnt > WS_MAX_PERSISTENT_COUNT) {
2875 WDP_LOGE("Persistent group count exceeded or parsing error");
2876 __WDP_LOG_FUNC_EXIT__;
2880 wfd_persistent_groups = (wfd_oem_persistent_group_s*) calloc(1, cnt * sizeof(wfd_oem_persistent_group_s));
2881 for(i = 0; i < cnt; i++) {
2882 WDP_LOGD("----persistent group [%d]----", i);
2883 WDP_LOGD("network_id=%d", networks[i].network_id);
2884 WDP_LOGD("ssid=%s", networks[i].ssid);
2885 WDP_LOGD("bssid=" MACSTR, MAC2STR(networks[i].bssid));
2886 WDP_LOGD("flags=%x", networks[i].flags);
2888 wfd_persistent_groups[i].network_id = networks[i].network_id;
2889 strncpy(wfd_persistent_groups[i].ssid, networks[i].ssid, WS_SSID_LEN);
2890 wfd_persistent_groups[i].ssid[WS_SSID_LEN] = '\0';
2891 memcpy(wfd_persistent_groups[i].go_mac_address, networks[i].bssid, WS_MACADDR_LEN);
2895 *groups = wfd_persistent_groups;
2897 __WDP_LOG_FUNC_EXIT__;
2901 int ws_remove_persistent_group(char *ssid, unsigned char *bssid)
2903 __WDP_LOG_FUNC_ENTER__;
2904 ws_sock_data_s *sock = g_pd->common;
2905 char cmd[80] = {0, };
2906 char reply[1024]={0,};
2909 ws_network_info_s networks[WS_MAX_PERSISTENT_COUNT];
2912 if (!ssid || !bssid) {
2913 WDP_LOGE("Invalid parameter");
2918 WDP_LOGE("Socket is NULL");
2922 memset(networks, 0, (sizeof(ws_network_info_s) * WS_MAX_PERSISTENT_COUNT));
2924 strncpy(cmd, WS_CMD_LIST_NETWORKS, sizeof(cmd));
2925 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2927 WDP_LOGE("Failed to send command to wpa_supplicant");
2928 __WDP_LOG_FUNC_EXIT__;
2932 if (strstr(reply, "FAIL")) {
2933 WDP_LOGE("Failed to get list of networks");
2934 __WDP_LOG_FUNC_EXIT__;
2937 WDP_LOGD("Succeeded to get list of networks");
2939 _parsing_networks(reply, networks, &network_count);
2941 for(i=0;i<network_count;i++) {
2942 WDP_LOGD("----persistent group [%d]----", i);
2943 WDP_LOGD("network_id=%d", networks[i].network_id);
2944 WDP_LOGD("ssid=%s", networks[i].ssid);
2945 WDP_LOGD("bssid=" MACSTR, MAC2STR(networks[i].bssid));
2946 WDP_LOGD("flags=%x", networks[i].flags);
2948 if (!memcmp(bssid, networks[i].bssid, WS_MACADDR_LEN) && !strcmp(ssid, networks[i].ssid)) {
2950 WDP_LOGD("Persistent group found [%d: %s]", networks[i].network_id, ssid);
2952 memset(cmd, 0x0, sizeof(cmd));
2953 memset(reply, 0x0, sizeof(reply));
2955 snprintf(cmd, sizeof(cmd), WS_CMD_REMOVE_NETWORK " %d", networks[i].network_id);
2956 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2958 WDP_LOGE("Failed to send command to wpa_supplicant");
2959 __WDP_LOG_FUNC_EXIT__;
2963 if (strstr(reply, "FAIL")) {
2964 WDP_LOGE("Failed to remove persistent group");
2965 __WDP_LOG_FUNC_EXIT__;
2968 WDP_LOGD("Succeeded to remove persistent group");
2974 if (i == network_count) {
2975 WDP_LOGE("Persistent group not found [%s]", ssid);
2979 __WDP_LOG_FUNC_EXIT__;
2983 int ws_set_persistent_reconnect(unsigned char *bssid, int reconnect)
2985 __WDP_LOG_FUNC_ENTER__;
2986 ws_sock_data_s *sock = g_pd->common;
2987 char cmd[80] = {0, };
2988 char reply[1024]={0,};
2992 WDP_LOGE("Socket is NULL");
2996 snprintf(cmd, sizeof(cmd), "%s persistent_reconnect %d", WS_CMD_SET, reconnect);
2997 res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
2999 WDP_LOGE("Failed to send command to wpa_supplicant");
3000 __WDP_LOG_FUNC_EXIT__;
3004 if (strstr(reply, "FAIL")) {
3005 WDP_LOGE("Failed to register WFDS service");
3006 __WDP_LOG_FUNC_EXIT__;
3009 WDP_LOGD("Succeeded to register WFDS service");
3011 __WDP_LOG_FUNC_EXIT__;