#define IPSTR_LEN 16
#define PINSTR_LEN 8
#define PASSPHRASE_LEN 8
+#define QUERY_HANDLE_LIMIT 256
#if 0
typedef enum {
WFD_SCAN_MODE_PASSIVE,
} wfd_scan_mode_e;
+typedef struct {
+ wifi_direct_service_type_e service_type;
+ int ref_counter;
+ char *service_string;
+ int service_str_length;
+} wfd_service_s;
+
+typedef struct {
+ int handle;
+ int ref_counter;
+ unsigned char mac_addr[6];
+ wifi_direct_service_type_e service_type;
+ char *query_string;
+}wfd_query_s;
+
typedef enum {
WFD_PEER_STATE_DISCOVERED,
WFD_PEER_STATE_CONNECTING,
int group_flags;
int wps_mode;
+ GList *services;
+
int wfd_dev_info;
int wfd_ctrl_port;
int wfd_max_tput;
void *group;
+ GList *query_handles;
+
void *oem_ops;
void *plugin_handle;
} wfd_manager_s;
int wfd_manager_get_req_wps_mode(int *req_wps_mode);
int wfd_manager_set_req_wps_mode(int req_wps_mode);
+int wfd_manager_service_add(wfd_manager_s *manager, wifi_direct_service_type_e type, char *data);
+int wfd_manager_service_del(wfd_manager_s *manager, wifi_direct_service_type_e type, char *data);
+int wfd_manager_serv_disc_req(wfd_manager_s *manager, unsigned char* mad_addr, wifi_direct_service_type_e type, char *data);
+int wfd_manager_serv_disc_cancel(wfd_manager_s *manager, int handle);
+int wfd_manager_init_service(wfd_device_s *device);
+int wfd_manager_init_query(wfd_manager_s *manager);
+
int wfd_manager_local_config_set(wfd_manager_s *manager);
int wfd_manager_activate(wfd_manager_s *manager);
int wfd_manager_deactivate(wfd_manager_s *manager);
return ops->set_persistent_reconnect(bssid, reconnect);
}
+int wfd_oem_service_add(wfd_oem_ops_s *ops, wfd_oem_service_e type, char *data)
+{
+ if (!ops || !ops->service_add) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ return ops->service_add(type, data);
+}
+
+int wfd_oem_service_del(wfd_oem_ops_s *ops, wfd_oem_service_e type, char *data)
+{
+ if (!ops || !ops->service_del) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ return ops->service_del(type, data);
+}
+
+int wfd_oem_serv_disc_req(wfd_oem_ops_s *ops, unsigned char* MAC, wfd_oem_service_e type, char *data)
+{
+ if (!ops || !ops->serv_disc_req) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ return ops->serv_disc_req(MAC, type, data);
+}
+
+int wfd_oem_serv_disc_cancel(wfd_oem_ops_s *ops, int identifier)
+{
+ if (!ops || !ops->serv_disc_cancel) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ return ops->serv_disc_cancel(identifier);
+}
WFD_OEM_EVENT_CONNECTED, // 25
WFD_OEM_EVENT_DISCONNECTED,
+ WFD_OEM_EVENT_SERV_DISC_RESP,
+
WFD_OEM_EVENT_TERMINATING,
WFD_OEM_EVENT_MAX,
WFD_OEM_EDATA_TYPE_CONN,
WFD_OEM_EDATA_TYPE_INVITE,
WFD_OEM_EDATA_TYPE_GROUP,
+ WFD_OEM_EDATA_TYPE_SERVICE,
} ws_event_type_e;
typedef enum {
WFD_OEM_DEV_ROLE_GO,
} wfd_oem_dev_role_e;
+typedef enum
+{
+ WFD_OEM_SERVICE_ALL,
+ WFD_OEM_SERVICE_BONJOUR,
+ WFD_OEM_SERVICE_UPNP,
+ WFD_OEM_SERVICE_WSDISCOVERY,
+ WFD_OEM_SERVICE_WIFIDISPLAY,
+ WFD_OEM_SERVICE_VENDORSPEC = 0xff,
+} wfd_oem_service_e;
+
typedef struct {
int scan_mode;
int scan_time;
int (*get_persistent_groups) (wfd_oem_persistent_group_s **groups, int *group_count);
int (*remove_persistent_group) (char *ssid, unsigned char *bssid);
int (*set_persistent_reconnect) (unsigned char *bssid, int reconnect);
+
+ int (*service_add) (wfd_oem_service_e type,char *data);
+ int (*service_del) (wfd_oem_service_e type,char *data);
+ int (*serv_disc_req) (unsigned char* MAC, wfd_oem_service_e type,char *data);
+ int (*serv_disc_cancel) (int identifier);
+
} wfd_oem_ops_s;
int wfd_oem_init(wfd_oem_ops_s *ops, wfd_oem_event_cb event_callback, void *user_data);
int wfd_oem_remove_persistent_group(wfd_oem_ops_s *ops, char *ssid, unsigned char *bssid);
int wfd_oem_set_persistent_reconnect(wfd_oem_ops_s *ops, unsigned char *bssid, int reconnect);
+int wfd_oem_service_add(wfd_oem_ops_s *ops, wfd_oem_service_e type, char *data);
+int wfd_oem_service_del(wfd_oem_ops_s *ops, wfd_oem_service_e type, char *data);
+int wfd_oem_serv_disc_req(wfd_oem_ops_s *ops, unsigned char* MAC, wfd_oem_service_e type, char *data);
+int wfd_oem_serv_disc_cancel(wfd_oem_ops_s *ops, int identifier);
+
#endif /* __WIFI_DIRECT_OEM_H__ */
+Fri, 24 Jan 2014 Jiung Yu <jiung.yu@samaung.com> (1.0.8)
+ * Add Wifi Direct Service Discovery
+
Tue, 15 Jan 2014 Jiung Yu <jiung.yu@samaung.com> (1.0.7)
* Replace file execution method
Name: wifi-direct-manager
Summary: Wi-Fi Direct manger
-Version: 1.0.7
+Version: 1.0.8
Release: 1
Group: Network & Connectivity/Wireless
License: Apache-2.0
{"P2P-GROUP-STARTED", WS_EVENT_GROUP_STARTED},
{"P2P-GROUP-REMOVED", WS_EVENT_GROUP_REMOVED},
+ //service
+ {"P2P-SERV-DISC-RESP", WS_EVENT_SERV_DISC_RESP},
+
{"CTRL-EVENT-TERMINATING", WS_EVENT_TERMINATING},
};
.get_persistent_groups = ws_get_persistent_groups,
.remove_persistent_group = ws_remove_persistent_group,
.set_persistent_reconnect = ws_set_persistent_reconnect,
+
+ .service_add = ws_service_add,
+ .service_del = ws_service_del,
+ .serv_disc_req = ws_serv_disc_req,
+ .serv_disc_cancel = ws_serv_disc_cancel,
};
static ws_plugin_data_s *g_pd;
}
break;
+ case WS_EVENT_SERV_DISC_RESP:
+ {
+ _ws_txt_to_mac(info_str, data->dev_addr);
+ info_str += OEM_MACSTR_LEN;
+
+ WDP_LOGD("service tlv is %s", info_str);
+
+ if (!strlen(info_str)) {
+ WDP_LOGD("Nothing to parse anymore");
+ data->edata_type = WFD_OEM_EDATA_TYPE_NONE;
+ break;
+ }
+ data->edata = (void*)strndup(info_str, strlen(info_str));
+ data->edata_type = WFD_OEM_EDATA_TYPE_SERVICE;
+ }
+ break;
default:
WDP_LOGE("Unknown event");
break;
{
__WDP_LOG_FUNC_ENTER__;
ws_sock_data_s * sd = (ws_sock_data_s*) data;
- char msg[1024] = {0, };
+ char msg[2048] = {0, };
char *param;
int event_id = -1;
wfd_oem_event_s *event = NULL;
break;
case WS_EVENT_INVITATION_RECEIVED:
{
- wfd_oem_invite_data_s* edata = NULL;
- edata = (wfd_oem_invite_data_s*) event->edata;
event_id = WFD_OEM_EVENT_INVITATION_REQ;
}
break;
case WS_EVENT_STA_DISCONNECTED:
event_id = WFD_OEM_EVENT_STA_DISCONNECTED;
break;
+ case WS_EVENT_SERV_DISC_RESP:
+ event_id = WFD_OEM_EVENT_SERV_DISC_RESP;
+ break;
case WS_EVENT_TERMINATING:
event_id = WFD_OEM_EVENT_TERMINATING;
break;
return 0;
}
+int ws_service_add(wfd_oem_service_e service_type, char *data)
+{
+ __WDP_LOG_FUNC_ENTER__;
+ ws_sock_data_s *sock = g_pd->common;
+ char cmd[256] = {0, };
+ char reply[1024]={0,};
+ int res;
+
+ if (!sock) {
+ WDP_LOGE("Socket is NULL");
+ return -1;
+ }
+ if (!data || !strlen(data)) {
+ WDP_LOGE( "Invalid parameter");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (service_type == WFD_OEM_SERVICE_BONJOUR)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_ADD "bonjour %s", data);
+ else if (service_type == WFD_OEM_SERVICE_UPNP)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_ADD "upnp %s", data);
+ else if (service_type ==WFD_OEM_SERVICE_VENDORSPEC)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_ADD "vendor %s", data);
+ else{
+ WDP_LOGE( "Invalid parameter");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
+ if (res < 0) {
+ WDP_LOGE("Failed to send command to wpa_supplicant");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (strstr(reply, "FAIL")) {
+ WDP_LOGE("Failed to add service");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+ WDP_LOGD("Succeeded to add service");
+
+ __WDP_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+int ws_service_del(wfd_oem_service_e service_type, char *data)
+{
+ __WDP_LOG_FUNC_ENTER__;
+ ws_sock_data_s *sock = g_pd->common;
+ char cmd[256] = {0, };
+ char reply[1024]={0,};
+ int res;
+
+ if (!sock) {
+ WDP_LOGE("Socket is NULL");
+ return -1;
+ }
+ if (!data || !strlen(data)) {
+ WDP_LOGE( "Invalid parameter");
+ __WDP_LOG_FUNC_EXIT__;
+ return 1;
+ }
+
+ if ( service_type == WFD_OEM_SERVICE_BONJOUR)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_DEL "bonjour %s", data);
+ else if (service_type == WFD_OEM_SERVICE_UPNP)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_DEL "upnp %s", data);
+ else if (service_type ==WFD_OEM_SERVICE_VENDORSPEC)
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERVICE_DEL "vendor %s", data);
+ else{
+ WDP_LOGE( "Invalid parameter");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
+ if (res < 0) {
+ WDP_LOGE("Failed to send command to wpa_supplicant");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (strstr(reply, "FAIL")) {
+ WDP_LOGE("Failed to delete service");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+ WDP_LOGD("Succeeded to delete service");
+
+ __WDP_LOG_FUNC_EXIT__;
+ return 0;
+}
+
+static int _ws_query_generation(unsigned char* MAC, wfd_oem_service_e type, char *data, char *buff)
+{
+ __WDP_LOG_FUNC_ENTER__;
+ int res=0;
+ int tlv_len=0;
+ char *query=NULL;
+
+ switch(type){
+ case WFD_OEM_SERVICE_ALL:
+ query=strndup(SERVICE_TYPE_ALL,8);
+ break;
+ case WFD_OEM_SERVICE_BONJOUR:
+ query=strndup(SERVICE_TYPE_BONJOUR,8);
+ break;
+ case WFD_OEM_SERVICE_UPNP:
+ query=strndup(SERVICE_TYPE_UPNP,8);
+ break;
+ case WFD_OEM_SERVICE_VENDORSPEC:
+ query=strndup(SERVICE_TYPE_VENDOR_SPECIFIC,8);
+ break;
+ default:
+ WDP_LOGE( "Invalid parameter");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ break;
+ }
+
+ if(data && (tlv_len = strlen(data)))
+ {
+ if(type == WFD_OEM_SERVICE_UPNP)
+ {
+ snprintf(buff, 256, WS_CMD_P2P_SERV_DISC_REQ MACSTR " upnp %s", MAC2STR(MAC), data);
+ }else{
+
+ if(type == WFD_OEM_SERVICE_BONJOUR)
+ tlv_len = tlv_len/2 + 2;
+
+ query[0] = '0' + (char)(tlv_len/16);
+ if(tlv_len%16 < 10)
+ query[1] = '0' + (char)(tlv_len%16);
+ else
+ query[1] = 'a' + (char)(tlv_len%16) - 10;
+ snprintf(buff, 256, WS_CMD_P2P_SERV_DISC_REQ MACSTR " %s%s", MAC2STR(MAC), query, data);
+ }
+ }else{
+ snprintf(buff, 256, WS_CMD_P2P_SERV_DISC_REQ MACSTR " %s", MAC2STR(MAC), query);
+ }
+ if(query != NULL)
+ free(query);
+ __WDP_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int ws_serv_disc_req(unsigned char* MAC, wfd_oem_service_e type, char *data)
+{
+ __WDP_LOG_FUNC_ENTER__;
+ ws_sock_data_s *sock = g_pd->common;
+ char cmd[256] = {0, };
+ char reply[1024]={0,};
+ int res;
+
+ if (!sock) {
+ WDP_LOGE("Socket is NULL");
+ return -1;
+ }
+
+ res = _ws_query_generation(MAC, type, data, cmd);
+ if (res < 0) {
+ WDP_LOGE("Failed to generate query");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
+ if (res < 0) {
+ WDP_LOGE("Failed to send command to wpa_supplicant");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (strstr(reply, "FAIL")) {
+ WDP_LOGE("Failed to request service discovery");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ res = strtol(reply, NULL, 16);
+ WDP_LOGD("Succeeded to request service discovery(%d)", res);
+ __WDP_LOG_FUNC_EXIT__;
+ return res;
+
+}
+
+int ws_serv_disc_cancel(int identifier)
+{
+ __WDP_LOG_FUNC_ENTER__;
+ ws_sock_data_s *sock = g_pd->common;
+ char cmd[80] = {0, };
+ char reply[1024]={0,};
+ int res;
+
+ if (!sock) {
+ WDP_LOGE("Socket is NULL");
+ return -1;
+ }
+
+ snprintf(cmd, sizeof(cmd), WS_CMD_P2P_SERV_DISC_CANCEL " %x", identifier);
+
+ res = _ws_send_cmd(sock->ctrl_sock, cmd, (char*) reply, sizeof(reply));
+ if (res < 0) {
+ WDP_LOGE("Failed to send command to wpa_supplicant");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (strstr(reply, "FAIL")) {
+ WDP_LOGE("Failed to cancel service discovery");
+ __WDP_LOG_FUNC_EXIT__;
+ return -1;
+ }
+ WDP_LOGD("Succeeded to cancel service discovery");
+
+ __WDP_LOG_FUNC_EXIT__;
+ return 0;
+
+}
+
int ws_get_persistent_groups(wfd_oem_persistent_group_s **groups, int *group_count)
{
__WDP_LOG_FUNC_ENTER__;
#define WS_NETFLAG_LEN 32
#define WS_MAX_PERSISTENT_COUNT 20
+#define SERVICE_TYPE_ALL "02000001"
+#define SERVICE_TYPE_BONJOUR "02000102"
+#define SERVICE_TYPE_UPNP "02000203"
+#define SERVICE_TYPE_VENDOR_SPECIFIC "0200ff04"
+#define CMD_LENGTH 80
+
/* Config Method bitmap */
#define WS_CONFIG_METHOD_DISPLAY 0x0008
#define WS_CONFIG_METHOD_PUSHBUTTON 0x0080
#define WS_STR_PERSISTENT " persistent"
#define WS_STR_FREQ_2G " freq=2"
+#define WS_CMD_P2P_SERVICE_ADD "P2P_SERVICE_ADD "
+#define WS_CMD_P2P_SERVICE_DEL "P2P_SERVICE_DEL "
+#define WS_CMD_P2P_SERV_DISC_REQ "P2P_SERV_DISC_REQ "
+#define WS_CMD_P2P_SERV_DISC_CANCEL "P2P_SERV_DISC_CANCEL_REQ "
+
typedef enum {
WS_IFTYPE_NONE,
WS_IFTYPE_STATION,
WS_EVENT_GROUP_STARTED,
WS_EVENT_GROUP_REMOVED,
+ WS_EVENT_SERV_DISC_RESP,
+
WS_EVENT_TERMINATING,
WS_EVENT_LIMIT,
int ws_remove_persistent_group(char *ssid, unsigned char *bssid);
int ws_set_persistent_reconnect(unsigned char *bssid, int reconnect);
+int ws_service_add(wfd_oem_service_e type,char *data);
+int ws_service_del(wfd_oem_service_e type,char *data);
+int ws_serv_disc_req(unsigned char* MAC, wfd_oem_service_e type,char *data);
+int ws_serv_disc_cancel(int identifier);
+
#endif /* __WFD_PLUGIN_WPASUPPLICANT_H__ */
return "WIFI_DIRECT_CMD_SET_DEVICE_NAME";
case WIFI_DIRECT_CMD_SET_OEM_LOGLEVEL:
return "WIFI_DIRECT_CMD_SET_OEM_LOGLEVEL";
-
+ case WIFI_DIRECT_CMD_SERVICE_ADD:
+ return "WIFI_DIRECT_CMD_SERVICE_ADD";
+ case WIFI_DIRECT_CMD_SERVICE_DEL:
+ return "WIFI_DIRECT_CMD_SERVICE_DEL";
+ case WIFI_DIRECT_CMD_SERV_DISC_REQ:
+ return "WIFI_DIRECT_CMD_SERV_DISC_REQ";
+ case WIFI_DIRECT_CMD_SERV_DISC_CANCEL:
+ return "WIFI_DIRECT_CMD_SERV_DISC_CANCEL";
default:
return "WIFI_DIRECT_CMD_INVALID";
wfd_destroy_group(manager, GROUP_IFNAME);
wfd_destroy_session(manager);
+ wfd_manager_init_service(manager->local);
+ wfd_manager_init_query(manager);
wfd_peer_clear_all(manager);
WDS_LOGD("peer count[%d], peers[%d]", manager->peer_count, manager->peers);
wfd_local_reset_data(manager);
case WIFI_DIRECT_CMD_GENERATE_WPS_PIN: // manager
// TODO: implement in plugin
break;
+ case WIFI_DIRECT_CMD_SERVICE_ADD:
+ {
+ char *buff = NULL;
+
+ buff = (char *)calloc(sizeof(char), req.cmd_data_len);
+ res = _wfd_read_from_client(sock, buff, req.cmd_data_len);
+ if (res < 0) {
+ WDS_LOGE("Failed to get service data");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ free(buff);
+ break;
+ }
+
+ res = wfd_manager_service_add(manager, req.data.int1, buff);
+ if (res < 0) {
+ WDS_LOGE("Failed to add service");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ }
+
+ free(buff);
+ }
+ break;
+ case WIFI_DIRECT_CMD_SERVICE_DEL:
+ {
+ char *buff = NULL;
+
+ buff = (char *)calloc(sizeof(char),req.cmd_data_len);
+ res = _wfd_read_from_client(sock, buff, req.cmd_data_len);
+ if (res < 0) {
+ WDS_LOGE("Failed to get service data");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ free(buff);
+ break;
+ }
+
+ res = wfd_manager_service_del(manager, req.data.int1, buff);
+ if (res < 0) {
+ WDS_LOGE("Failed to delete service");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ }
+
+ free(buff);
+ }
+ break;
+ case WIFI_DIRECT_CMD_SERV_DISC_REQ:
+ {
+ char *buff = NULL;
+
+ if(req.cmd_data_len != 0)
+ {
+ buff = (char*)calloc(sizeof(char),req.cmd_data_len);
+ res = _wfd_read_from_client(sock, buff, req.cmd_data_len);
+ if (res < 0) {
+ WDS_LOGE("Failed to get service data");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ free(buff);
+ break;
+ }
+ }
+
+ res = wfd_manager_serv_disc_req(manager,req.data.mac_addr, req.data.int1, buff);
+ if (res < 0) {
+ WDS_LOGE("Failed to requset service discovery");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ }
+ rsp.param1 = res;
+
+ if(buff != NULL)
+ free(buff);
+ }
+ break;
+ case WIFI_DIRECT_CMD_SERV_DISC_CANCEL:
+ {
+ res = wfd_manager_serv_disc_cancel(manager, req.data.int1);
+ if (res < 0) {
+ WDS_LOGE("Failed to delete service cancel");
+ rsp.result = WIFI_DIRECT_ERROR_OPERATION_FAILED;
+ }
+ }
+ break;
default:
WDS_LOGE("Unknown command[%d]", req.cmd);
rsp.result = WIFI_DIRECT_ERROR_NOT_PERMITTED;
return 0;
}
+static int hex2num(const char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+static int hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+int hexstr2bin(const char *hex, int len, char *buf)
+{
+ int i;
+ int a;
+ const char *ipos = hex;
+ char *opos = buf;
+
+ for (i = 0; i < len; i++) {
+ a = hex2byte(ipos);
+ if (a < 0)
+ return -1;
+ *opos++ = a;
+ ipos += 2;
+ }
+ return 0;
+}
+
+static int _wfd_get_stlv_len(const char* value)
+{
+ int a, b;
+ a = hex2byte(value +2);
+ b = hex2byte(value);
+
+ if( a >= 0 && b >= 0)
+ return ( a << 8) | b;
+ else
+ return -1;
+}
+
+static int _wfd_service_add(wfd_device_s *device, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_service_s *service = NULL;
+ GList *temp = NULL;
+ int res = 0;
+
+ temp = g_list_first(device->services);
+ while (temp) {
+ service = temp->data;
+
+ if(type == service->service_type &&
+ !strcmp(data, service->service_string))
+ {
+ WDS_LOGD("Service found");
+ break;
+ }
+ temp = g_list_next(temp);
+ service = NULL;
+ }
+
+ if (service) {
+ WDS_LOGE("service already exist");
+ free(data);
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+ }
+ service = (wfd_service_s*) calloc(1, sizeof(wfd_service_s));
+ service->service_string = data;
+ service->service_str_length = strlen(data);
+ service->service_type = type;
+ device->services = g_list_prepend(device->services, service);
+
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+static int _wfd_update_service(wfd_device_s *peer, char * data, wifi_direct_service_type_e type, int length)
+{
+ wfd_service_s * service;
+ int res = 0;
+ char *temp = NULL;
+ char *ptr = NULL;
+
+ if (!peer || !data) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+ switch (type)
+ {
+ case WIFI_DIRECT_SERVICE_BONJOUR:
+ {
+ temp = strndup(data, length*2);
+ res = _wfd_service_add(peer, type, temp);
+ break;
+ }
+ case WIFI_DIRECT_SERVICE_UPNP:
+ {
+ temp = calloc(1, length);
+ hexstr2bin(data +2, length - 1, temp);
+ temp[length - 1] = '\0';
+
+ ptr = strtok(temp, ",");
+
+ while(ptr != NULL)
+ {
+ res = _wfd_service_add(peer, type, strndup(ptr, strlen(ptr)));
+ ptr = strtok(NULL, ",");
+ }
+
+ if(temp)
+ free(temp);
+ break;
+ }
+ case WIFI_DIRECT_SERVICE_VENDORSPEC:
+ {
+ temp = calloc(1, length + 1);
+ hexstr2bin(data, length, temp);
+ temp[length] = '\0';
+
+ res = _wfd_service_add(peer, type, temp);
+ break;
+ }
+ default:
+ {
+ res = -1;
+ break;
+ }
+ }
+ return res;
+}
+
+static int _wfd_event_update_service(wfd_manager_s *manager, wfd_device_s *peer, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ int res = 0;
+ int s_len = 0;
+ char *pos = data;
+ char *end = NULL;
+ wifi_direct_service_type_e service_tlv_type;
+ int status = 0;
+
+ if (!peer || !data) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+ end = data + strlen(data);
+
+ while(pos <= end -10){// This is raw data that is not passed any exception handling ex> length, value, ...
+
+ s_len = _wfd_get_stlv_len(pos);
+ pos += 4;
+ if (pos + s_len*2 > end || s_len < 3) {
+ WDS_LOGD("Unexpected Response Data or length: %d", s_len);
+ break;
+ }
+
+ service_tlv_type = hex2byte(pos);
+ if (service_tlv_type < 0) {
+ WDS_LOGD("Unexpected Response service type: %d", service_tlv_type);
+ pos+=(s_len)*2;
+ continue;
+ }else if (service_tlv_type == 255)
+ service_tlv_type = WIFI_DIRECT_SERVICE_VENDORSPEC;
+
+ pos += 4;
+ status = hex2byte(pos);
+ pos += 2;
+
+ if (status == 0)
+ {
+ res = _wfd_update_service(peer, pos, service_tlv_type, s_len -3);
+ if (res != 0) {
+ WDS_LOGE("Invalid type");
+ }
+ } else
+ WDS_LOGD("Service Reaponse TLV status is not vaild status: %d", status);
+ pos+=(s_len-3)*2;
+ }
+ __WDS_LOG_FUNC_EXIT__;
+ return 0;
+}
+
int wfd_process_event(void *user_data, void *data)
{
__WDS_LOG_FUNC_ENTER__;
manager->scan_mode = WFD_SCAN_MODE_ACTIVE;
}
break;
+ case WFD_OEM_EVENT_SERV_DISC_RESP:
+ {
+ wfd_device_s *peer = NULL;
+ if(event->edata_type != WFD_OEM_EDATA_TYPE_SERVICE)
+ {
+ WDS_LOGD("There is no service to register");
+ break;
+ }
+ peer = wfd_peer_find_by_dev_addr(manager, event->dev_addr);
+ if (!peer) {
+ WDS_LOGD("serv_disc_resp from unknown peer. Discard it");
+ break;
+ }
+ res = _wfd_event_update_service(manager, peer, (char*) event->edata);
+ if (res < 0) {
+ WDS_LOGE("Failed to update peer service data");
+ }
+ }
+ break;
default:
WDS_LOGE("Unknown event [event ID: %d]", event->event_id);
break;
member = temp->data;
WDS_LOGD("%dth member[%s] freed", count, member->dev_name);
if (member) // Temporary. Sometimes manager crashed
+ {
+ wfd_manager_init_service(member);
free(member);
+ }
temp = g_list_next(temp);
count++;
}
return res;
}
+static int _wfd_manager_service_copy(char* dst, GList* services, int dst_length)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_service_s *service = NULL;
+ GList *temp = NULL;
+ char* ptr = dst;
+ int length = dst_length;
+ int res = 0;
+
+ temp = g_list_first(services);
+ while (temp) {
+
+ service = temp->data;
+ if(length < service->service_str_length + 4)
+ {
+ WDS_LOGD("There is not enough space to reserve service list");
+ break;
+ }
+
+ memcpy(ptr, service->service_string, service->service_str_length);
+ ptr+=service->service_str_length;
+ strncpy(ptr," ,\n",3);
+ ptr+=3;
+ length = length - service->service_str_length - 3;
+
+ temp = g_list_next(temp);
+ }
+ *ptr='\0';
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
int wfd_manager_get_peers(wfd_manager_s *manager, wfd_discovery_entry_s **peers_data)
{
__WDS_LOG_FUNC_ENTER__;
temp = g_list_next(temp);
manager->peers = g_list_remove(manager->peers, peer);
manager->peer_count--;
+ wfd_manager_init_service(peer);
free(peer);
peer = NULL;
continue;
memcpy(peers[count].mac_address, peer->dev_addr, MACADDR_LEN);
memcpy(peers[count].intf_address, peer->intf_addr, MACADDR_LEN);
peers[count].channel = peer->channel;
- peers[count].services = 0;
peers[count].is_group_owner = peer->dev_role == WFD_DEV_ROLE_GO;
peers[count].is_persistent_go = peer->group_flags & WFD_OEM_GROUP_FLAG_PERSISTENT_GROUP;
peers[count].is_connected = peer->dev_role == WFD_DEV_ROLE_GC;
peers[count].wps_cfg_methods = peer->config_methods;
peers[count].category = peer->pri_dev_type;
peers[count].subcategory = peer->sec_dev_type;
+ _wfd_manager_service_copy(peers[count].services, peer->services, 1024);
count++;
WDS_LOGD("%dth peer [%s]", count, peer->dev_name);
peers[count].subcategory = peer->sec_dev_type;
peers[count].channel = peer->channel;
peers[count].is_p2p = 1;
- peers[count].services = 0;
+ _wfd_manager_service_copy(peers[count].services, peer->services, 1024);
WDS_LOGD("%dth member converted[%s]", count, peers[count].device_name);
count++;
}
return 0;
}
+static wfd_service_s *_wfd_service_find(wfd_device_s *device, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_service_s *result = NULL;
+ GList *temp = NULL;
+ int cmp_result = 0;
+
+ temp = g_list_first(device->services);
+ while (temp) {
+ result = temp->data;
+
+ if(result->service_type == WIFI_DIRECT_SERVICE_BONJOUR)
+ cmp_result = strncmp(data, result->service_string, strlen(data));
+ else
+ cmp_result = strcmp(data, result->service_string);
+
+ if(type == result->service_type && !cmp_result)
+ {
+ WDS_LOGD("Service found");
+ break;
+ }
+ temp = g_list_next(temp);
+ result = NULL;
+ }
+ __WDS_LOG_FUNC_EXIT__;
+ return result;
+}
+
+static wfd_query_s *_wfd_query_find(wfd_manager_s *manager, unsigned char* mac_addr, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_query_s *query = NULL;
+ GList *temp = NULL;
+ int data_len = 0;
+
+ if(data != NULL)
+ data_len = strlen(data);
+
+ temp = g_list_first(manager->query_handles);
+ while (temp) {
+ query = temp->data;
+
+ if(!memcmp(query->mac_addr, mac_addr, MACADDR_LEN) &&
+ type == query->service_type)
+ {
+ if(data_len)
+ {
+ if(!strcmp(data, query->query_string))
+ {
+ WDS_LOGD("Query found");
+ break;
+ }
+ }else{
+ WDS_LOGD("Query found");
+ break;
+ }
+ }
+ temp = g_list_next(temp);
+ query = NULL;
+ }
+ __WDS_LOG_FUNC_EXIT__;
+ return query;
+}
+
+int wfd_manager_service_add(wfd_manager_s *manager, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_device_s * device = manager->local;
+ wfd_service_s * service;
+ int res = 0;
+
+ if (!device || !data) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ service = _wfd_service_find(device, type, data);
+ if (service) {
+ WDS_LOGE("service already exist");
+ service->ref_counter++;
+ __WDS_LOG_FUNC_EXIT__;
+ return 0;
+ }
+
+ res = wfd_oem_service_add(manager->oem_ops, type, data);
+ if (res < 0) {
+ WDS_LOGE("Failed to add service");
+ __WDS_LOG_FUNC_EXIT__;
+ return -1;
+ }
+
+ service = (wfd_service_s*) calloc(1, sizeof(wfd_service_s));
+ service->service_string = strndup(data, strlen(data));
+ service->service_str_length = strlen(data);
+ service->service_type = type;
+ service->ref_counter=1;
+ device->services = g_list_prepend(device->services, service);
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int wfd_manager_service_del(wfd_manager_s *manager, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_device_s * device = manager->local;
+ wfd_service_s* service;
+ int res = 0;
+
+ if (!device || !data) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+ service = _wfd_service_find(device, type, data);
+ if (!service) {
+ WDS_LOGE("Failed to find service");
+ res = -1;
+
+ }else if(service->ref_counter ==1)
+ {
+ res = wfd_oem_service_del(manager->oem_ops, type, data);
+ if (res < 0) {
+ WDS_LOGE("Failed to delete service");
+ __WDS_LOG_FUNC_EXIT__;
+ return -1;
+ }
+ device->services = g_list_remove(device->services, service);
+ free(service->service_string);
+ free(service);
+
+ }else{
+ service->ref_counter--;
+ }
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int wfd_manager_serv_disc_req(wfd_manager_s *manager, unsigned char* mad_addr, wifi_direct_service_type_e type, char *data)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_query_s* query;
+ int res = 0;
+
+ if (!manager) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+ query = _wfd_query_find(manager, mad_addr, type, data);
+ if (query) {
+ WDS_LOGE("Query already exist");
+ query->ref_counter++;
+ __WDS_LOG_FUNC_EXIT__;
+ return 0;
+ }
+
+ res = wfd_oem_serv_disc_req(manager->oem_ops, mad_addr, type, data);
+ if (res < 0) {
+ WDS_LOGE("Failed to request service discovery");
+ return res;
+ }
+ query = (wfd_query_s*) calloc(1, sizeof(wfd_query_s));
+ query->handle = res;
+ query->ref_counter=1;
+ memcpy(query->mac_addr, mad_addr, MACADDR_LEN);
+
+ if(data && strlen(data))
+ query->query_string = strndup(data, strlen(data));
+ query->service_type = type;
+ manager->query_handles = g_list_prepend(manager->query_handles, query);
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int wfd_manager_serv_disc_cancel(wfd_manager_s *manager, int handle)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_query_s *query = NULL;
+ GList *temp = NULL;
+ int res = 0;
+
+ temp = g_list_first(manager->query_handles);
+ while (temp) {
+ query = temp->data;
+
+ //TODO : compare the services
+ if(query->handle == handle)
+ {
+ WDS_LOGD("Query handle found");
+ break;
+ }
+ temp = g_list_next(temp);
+ query = NULL;
+ }
+
+ if(query == NULL) {
+ WDS_LOGE("handle does not exist");
+ return -1;
+ }else if(query->ref_counter ==1) {
+
+ res = wfd_oem_serv_disc_cancel(manager->oem_ops, query->handle);
+ if (res < 0) {
+ WDS_LOGE("Failed to cancel service discovery or already canceled");
+ }
+ manager->query_handles = g_list_remove(manager->query_handles, query);
+ if(query->query_string)
+ free(query->query_string);
+ free(query);
+ }else
+ query->ref_counter--;
+
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int wfd_manager_init_service(wfd_device_s *device)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_service_s* service = NULL;
+ GList *temp = NULL;
+ int res = 0;
+
+ if (!device) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ if(device->services)
+ {
+ temp = g_list_first(device->services);
+ while (temp) {
+ service = temp->data;
+ free(service->service_string);
+ free(service);
+ temp = g_list_next(temp);
+ }
+ g_list_free(device->services);
+ }
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
+int wfd_manager_init_query(wfd_manager_s *manager)
+{
+ __WDS_LOG_FUNC_ENTER__;
+ wfd_query_s *query = NULL;
+ GList *temp = NULL;
+ int res = 0;
+
+ if (!manager) {
+ WDS_LOGE("Invalid parameter");
+ return -1;
+ }
+
+ if(manager->query_handles)
+ {
+ temp = g_list_first(manager->query_handles);
+ while (temp) {
+ query = temp->data;
+
+ free(query->query_string);
+ free(query);
+ temp = g_list_next(temp);
+ }
+ g_list_free(manager->query_handles);
+ }
+
+ __WDS_LOG_FUNC_EXIT__;
+ return res;
+}
+
static wfd_manager_s *wfd_manager_init()
{
__WDS_LOG_FUNC_ENTER__;
manager->peers = g_list_remove(manager->peers, peer);
manager->peer_count--;
+ wfd_manager_init_service(peer);
free(peer);
__WDS_LOG_FUNC_EXIT__;
return 0;
temp = g_list_first(manager->peers);
while(temp) {
peer = (wfd_device_s*) temp->data;
+ wfd_manager_init_service(peer);
free(peer);
temp = g_list_next(temp);
manager->peer_count--;