RDK Documentation (Open Sourced RDK Components)
wifi_client_hal.c
1 /*
2 * If not stated otherwise in this file or this component's Licenses.txt file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2018 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19 
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <ctype.h>
25 #include <signal.h>
26 #include <wifi_client_hal.h>
27 #include <unistd.h>
28 #include <pthread.h>
29 #include "wifi_log.h"
30 #ifdef WIFI_CLIENT_ROAMING
31 #include <errno.h>
32 #include "cJSON.h"
33 #endif
34 #include <stdarg.h>
35 #include <sys/time.h>
36 //This call back will be invoked when client automatically connect to AP.
37 
38 wifi_connectEndpoint_callback callback_connect = NULL;
39 
40 //This call back will be invoked when client lost the connection to AP.
41 wifi_disconnectEndpoint_callback callback_disconnect;
42 
43 #include <wpa_ctrl.h>
44 
45 #include <stdint.h>
46 typedef uint8_t u8;
47 // added to be able to use wpa_supplicant's 'printf_decode' utility function to decode the SSIDs encoded by wpa_supplicant
48 extern size_t printf_decode(u8 *buf, size_t maxlen, const char *str);
49 
50 #define WPA_SUP_TIMEOUT 5000 /* 5 msec */
51 #define MAX_SSID_LEN 32 /* Maximum SSID name */
52 #define MAX_PASSWORD_LEN 64 /* Maximum password length */
53 #define ENET_LEN 17 /* Length of bytes for displaying an Ethernet address, e.g., 00:00:00:00:00:00.*/
54 #define CSPEC_LEN 20 /* Channel Spec string length */
55 #define RETURN_BUF_LENGTH (96*1024) /* Return buffer length */
56 #define BUFF_LEN_32 MAX_SSID_LEN /* Buffer Length 32 */
57 #define BUFF_LEN_64 64 /* Buffer Length 64*/
58 #define MAX_WPS_AP_COUNT 5 /* Max number of PBC enabled Access Points */
59 #define WPS_CON_TIMEOUT 120 /* WPS connection timeout */
60 
61 #define MAX_NEIGHBOR_LIMIT 32 /* Max number of APs in neighbor report */
62 #define PREVIOUS_AUTH_INVALID 2 /* Previous authentication no longer valid reason code */
63 #ifdef WIFI_CLIENT_ROAMING
64 #define WIFI_ROAMING_CONFIG_FILE "/opt/secure/wifi/wifi_roamingControl.json" /* Persistent storage for Roaming Configuration */
65 #define WIFI_DEFAULT_ROAMING_ENABLE false
66 #define WIFI_DEFAULT_PRE_ASSN_BEST_THRLD -67
67 #define WIFI_DEFAULT_PRE_ASSN_BEST_DELTA 3
68 #define WIFI_DEFAULT_BEST_DELTA_CONNECTED 12
69 #define WIFI_DEFAULT_POST_ASSN_SELF_STEER_THRESHOLD -75
70 #define WIFI_DEFAULT_POST_ASSN_SELF_STEER_TIMEFRAME 60
71 #define WIFI_DEFAULT_SELF_STEER_OVERRIDE_ENABLE false
72 #define WIFI_DEFAULT_BEST_DELTA_DISCONNECTED 8
73 #define WIFI_DEFAULT_AP_CONTROL_THRESHOLD -75
74 #define WIFI_DEFAULT_AP_CONTROL_TIMEFRAME 60
75 #define WIFI_DEFAULT_POST_ASSN_BACKOFF_TIME 2
76 #define WIFI_DEFAULT_POST_ASSN_DELTA 3
77 #define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS"
78 #define WIFI_MAX_POST_ASSN_BACKOFF_TIME 3600 /* Max back off timer(1 Hour) for Post Association Roaming */
79 #define WIFI_MAX_POST_ASSN_TIME_FRAME 36000 /* Max limit for Time frame (10 Hours) limit for Post Assoc timeFrame */
80 #endif
81 
82 
83 typedef enum {
84  WIFI_HAL_WPA_SUP_STATE_IDLE,
85  WIFI_HAL_WPA_SUP_STATE_CMD_SENT,
86  WIFI_HAL_WPA_SUP_CONNECTING,
87 } WIFI_HAL_WPA_SUP_STATE;
88 
89 typedef enum {
90  WIFI_HAL_WPA_SUP_SCAN_STATE_IDLE,
91  WIFI_HAL_WPA_SUP_SCAN_STATE_CMD_SENT,
92  WIFI_HAL_WPA_SUP_SCAN_STATE_STARTED,
93  WIFI_HAL_WPA_SUP_SCAN_STATE_RESULTS_RECEIVED,
94 } WIFI_HAL_WPA_SUP_SCAN_STATE;
95 
96 #ifdef WIFI_CLIENT_ROAMING
97 typedef enum {
98  WIFI_HAL_ROAM_STATE_ROAMING_IDLE,
99  WIFI_HAL_ROAM_STATE_SIGNAL_PROCESSING,
100  WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_STARTED,
101  WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_EXPIRED,
102  WIFI_HAL_ROAM_STATE_AP_SELECTION,
103  WIFI_HAL_ROAM_STATE_ROAMING_TRIGGERED,
104  WIFI_HAL_ROAM_STATE_ROAMING_SUCCESS,
105 } WIFI_HAL_ROAM_STATE;
106 
107 typedef enum {
108  WIFI_HAL_RRM_NEIGHBOR_REP_STATE_IDLE,
109  WIFI_HAL_RRM_NEIGHBOR_REP_RECEIVED,
110  WIFI_HAL_RRM_NEIGHBOR_REP_REQUEST_FAILED,
111  WIFI_HAL_RRM_NEIGHBOR_REP_STATE_INTERNAL_ERROR
112 } WIFI_HAL_RRM_NEIGHBOR_REP_STATUS;
113 
114 typedef enum {
115  WIFI_HAL_ROAMING_MODE_NOT_SET,
116  WIFI_HAL_ROAMING_MODE_SELF_STEERING,
117  WIFI_HAL_ROAMING_MODE_AP_STEERING,
118 } WIFI_HAL_ROAMING_MODE;
119 
120 typedef struct _wifi_rrm_neighbor_rep_request_t
121 {
122  char ssid[MAX_SSID_LEN + 1];
123  int lci;
124  int civic;
125 } wifi_rrm_neighbor_rep_request_t;
126 
127 typedef struct _wifi_rrm_neighbor_ap_t
128 {
129  char ssid[BUFF_LEN_32];
130  char bssid[BUFF_LEN_32];
131  char bssidInfo[BUFF_LEN_64];
132  int op_class;
133  int channel;
134  int phy_type;
135  int freq;
136 } wifi_rrm_neighbor_ap_t;
137 
138 typedef struct _wifi_neighbor_report_t
139 {
140  wifi_rrm_neighbor_ap_t neighbor_ap [MAX_NEIGHBOR_LIMIT];
141  int neighbor_cnt;
142 } wifi_rrm_neighbor_report_t;
143 #endif
144 
145 typedef struct _wifi_wps_pbc_ap
146 {
147  CHAR ap_SSID[MAX_SSID_LEN+1];
148  CHAR ap_BSSID[20];
149  INT ap_SignalStrength;
150  INT ap_Frequency;
151  WIFI_HAL_FREQ_BAND ap_FreqBand;
153 
154 /* The control and monitoring interface is defined and initialized during the init phase */
155 extern struct wpa_ctrl *g_wpa_ctrl;
156 extern struct wpa_ctrl *g_wpa_monitor;
157 
158 /* This mutex is used around wpa_supplicant calls. This is defined and initialized during the init phase */
159 extern pthread_mutex_t wpa_sup_lock;
160 
161 /* Use the same buffer from wifi_common_hal.c */
162 extern char cmd_buf[1024]; /* Buffer to pass the commands into */
163 extern char return_buf[RETURN_BUF_LENGTH]; /* Buffer that stores the return results */
164 
165 extern wifi_neighbor_ap_t ap_list[512];
166 extern uint32_t ap_count;
167 INT parse_scan_results(char *buf, size_t len);
168 
169 BOOL bNoAutoScan=FALSE;
170 char bUpdatedSSIDInfo=1;
171 BOOL bIsWpsCompleted = TRUE;
172 BOOL bIsPBCOverlapDetected = FALSE;
173 BOOL bWpsPBC = FALSE;
174 struct timespec timespec_wps_cancel;
175 
176 /* Initialize the state of the supplicant */
177 WIFI_HAL_WPA_SUP_STATE cur_sup_state = WIFI_HAL_WPA_SUP_STATE_IDLE;
178 WIFI_HAL_WPA_SUP_SCAN_STATE cur_scan_state_from_supp = WIFI_HAL_WPA_SUP_SCAN_STATE_IDLE;
179 extern WIFI_HAL_WPA_SUP_SCAN_STATE cur_scan_state;
180 
181 static char event_buf[4096]; /* Buffer to store the event results */
182 bool stop_monitor;
183 static int isPrivateSSID=1; /* Variable to check whether to save to conf file - Default value is 1 (Will save to conf file) */
184 size_t event_buf_len;
185 pthread_t wps_start_thread;
186 
187 
188 #ifdef WIFI_CLIENT_ROAMING
189 pthread_mutex_t wifi_roam_lock;
190 pthread_cond_t cond;
191 wifi_rrm_neighbor_report_t stRrmNeighborRpt;
192 pthread_t wifi_signal_mon_thread;
193 wifi_roamingCtrl_t pstRoamingCtrl; /* Global Roaming configuration */
194 int backOffRefreshed = 1;
195 INT postAssocBackOffTime = WIFI_DEFAULT_POST_ASSN_BACKOFF_TIME;
196 WIFI_HAL_RRM_NEIGHBOR_REP_STATUS cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_STATE_IDLE;
197 //WIFI_HAL_ROAMING_MODE cur_roaming_mode = WIFI_HAL_ROAMING_MODE_SELF_STEERING;
198 WIFI_HAL_ROAMING_MODE cur_roaming_mode = WIFI_HAL_ROAMING_MODE_AP_STEERING;
199 WIFI_HAL_ROAM_STATE cur_roaming_state = WIFI_HAL_ROAM_STATE_ROAMING_IDLE;
200 #endif // WIFI_CLIENT_ROAMING
201 
202 INT is_null_pointer(char* str);
203 
204 // Parse WPS-PBC enabled access points from Scan results
205 int parse_wps_pbc_accesspoints(char *buf,wifi_wps_pbc_ap_t ap_list[]);
206 // Start WPS operation with Band selection
207 void* start_wifi_wps_connection(void *param);
208 // Stop WPS operation on timeout
209 void stop_wifi_wps_connection();
210 // Check wether the station has dual band support
211 BOOL isDualBandSupported();
212 // Initiate WPS connection to athe given BSSID
213 int triggerWpsPush(char *bssid);
214 
215 #ifdef WIFI_CLIENT_ROAMING
216 // @brief This call will read the given file as argument
217 static char* readPersistentFile(char *fileName);
218 // @brief this call writes the given json data to the given fileName as argument
219 static int writeToPersistentFile (char *fileName, cJSON *pRoamingCtrl_data);
220 // @brief store wifi roaming configurations to persistent file
221 int persist_roaming_config(wifi_roamingCtrl_t*);
222 // @brief start wifi signal monitor thread for continues signal monitoring.
223 void start_wifi_signal_monitor_timer(void *arg);
224 
225 #endif
226 
227 char ssid_to_find[MAX_SSID_LEN+1] = {0};
228 char scanned_ssid[MAX_SSID_LEN+1] = {0};
229 
230 //This call back will be invoked when client automatically connect to AP.
231 wifi_connectEndpoint_callback callback_connect;
232 
233 //This call back will be invoked when client lost the connection to AP.
234 wifi_disconnectEndpoint_callback callback_disconnect;
235 
236 wifi_telemetry_ops_t *callback_telemetry;
237 
239 {
240  WIFI_LOG_INFO("Registering connect callback...\n");
241  callback_connect=callback_proc;
242 }
243 
245 {
246  WIFI_LOG_INFO("Registering disconnect callback...\n");
247  callback_disconnect=callback_proc;
248 }
249 
251 {
252  WIFI_LOG_INFO("Registering telemetry callback...\n");
253  callback_telemetry = telemetry_ops;
254 }
255 
256 void telemetry_init(char* name)
257 {
258  if (callback_telemetry) callback_telemetry->init(name);
259 }
260 
261 void telemetry_event_s(char* marker, char* value)
262 {
263  if (callback_telemetry) callback_telemetry->event_s(marker, value);
264 }
265 
266 void telemetry_event_d(char* marker, int value)
267 {
268  if (callback_telemetry) callback_telemetry->event_d(marker, value);
269 }
270 
271 /****** Helper functions ******/
272 char* getValue(const char *buf, const char *keyword) {
273  char *ptr = NULL;
274  char *saveptr = NULL;
275 
276  if(buf == NULL)
277  return NULL;
278  /* Goto the place where keyword is located in the string */
279  ptr = strstr(buf, keyword);
280  if (ptr == NULL) return NULL;
281 
282  strtok_r(ptr, "=", &saveptr);
283  return (strtok_r(NULL, "\n", &saveptr));
284 }
285 
286 char trimSpace(char *srcStr)
287 {
288  char *tmpPtr1;
289  char *tmpPtr2;
290  for(tmpPtr2=tmpPtr1=srcStr;*tmpPtr1;tmpPtr1++)
291  {
292  if(!isspace(*tmpPtr1))
293  *tmpPtr2++ = *tmpPtr1;
294  }
295  *tmpPtr2 = '\0';
296  return 1;
297 }
298 
299 int wpaCtrlSendCmd(char *cmd) {
300  size_t return_len=sizeof(return_buf)-1;
301  int ret;
302 
303  memset(return_buf, 0, return_len);
304  if(NULL == g_wpa_ctrl) {
305  WIFI_LOG_ERROR("Control interface is NULL. \n");
306  return -1;
307  }
308 
309  ret = wpa_ctrl_request(g_wpa_ctrl, cmd, strlen(cmd), return_buf, &return_len, NULL);
310 
311  if (ret == -2) {
312  WIFI_LOG_INFO("cmd=%s timed out \n", cmd);
313  return -2;
314  } else if (ret < 0) {
315  WIFI_LOG_INFO("cmd=%s failed \n", cmd);
316  return -3;
317  }
318  return 0;
319 }
320 
321 static int find_ssid_in_scan_results(const char* ssid)
322 {
323  bool found = false;
324  int i;
325  if(NULL == ssid || ssid[0] == '\0')
326  {
327  WIFI_LOG_ERROR("SSID to find is null/empty");
328  return found;
329  }
330  for (i = 0; i < ap_count; i++)
331  {
332  if (strncmp (ap_list[i].ap_SSID, ssid,MAX_SSID_LEN) == 0)
333  {
334  WIFI_LOG_INFO( "Found SSID match - bssid = %s rssi = %d ssid = %s\n",
335  ap_list[i].ap_BSSID, ap_list[i].ap_SignalStrength, ap_list[i].ap_SSID);
336  found = true;
337  }
338  else
339  {
340  WIFI_LOG_TRACE("No SSID match - bssid = %s rssi = %d ssid = %s\n",
341  ap_list[i].ap_BSSID, ap_list[i].ap_SignalStrength, ap_list[i].ap_SSID);
342  }
343  }
344  return found;
345 }
346 
347 static BOOL wpa_supplicant_conf_reset()
348 {
349  WIFI_LOG_INFO("Deleting conf file and making a new one\n");
350 
351  if (remove("/opt/secure/wifi/wpa_supplicant.conf") == 0)
352  {
353  WIFI_LOG_INFO("Removed File\n");
354  }
355  FILE *fp;
356  fp = fopen("/opt/secure/wifi/wpa_supplicant.conf", "w");
357  if (fp == NULL)
358  {
359  WIFI_LOG_INFO("Error in opening configuration file\n");
360  return false;
361  }
362  fprintf(fp, "ctrl_interface=/var/run/wpa_supplicant\n");
363  fprintf(fp, "update_config=1\n");
364  fclose(fp);
365  return true;
366 }
367 
368 static long timespec_diff_ms(struct timespec* ts1, struct timespec* ts2)
369 {
370  return ((ts2->tv_sec - ts1->tv_sec)*1000L) + ((ts2->tv_nsec - ts1->tv_nsec)/1000000);
371 }
372 
373 /******************************/
374 
375 /*********Callback thread to send messages to Network Service Manager *********/
376 void* monitor_thread_task(void *param)
377 {
378  char *start = NULL;
379  char *saveptr = NULL;
380 
381  char current_ssid[MAX_SSID_LEN+1] = {0}; // TODO: 32 chars won't be enough if undecoded SSID from wpa_supplicant has special chars (PACEXI5-2357)
382  char current_bssid[ENET_LEN+1] = {0}; // fixed length 18 chars (aa:bb:cc:dd:ee:ff + '\0')
383 
384  char last_disconnected_bssid[ENET_LEN+1] = {0};
385  int last_disconnected_reason_code = 0;
386  char last_disconnected_ssid[MAX_SSID_LEN+1] = {0};
387  char out_of_range_ssid[MAX_SSID_LEN+1] = {0};
388 
389  char tmp_return_buf[8192];
390 
391  wifiStatusCode_t connError;
392 #ifdef WIFI_CLIENT_ROAMING
393  pthread_mutex_init(&wifi_roam_lock,NULL);
394  pthread_condattr_t attr;
395 
396  pthread_condattr_init( &attr);
397  pthread_condattr_setclock( &attr, CLOCK_MONOTONIC);
398  pthread_cond_init( &cond, &attr);
399 #endif
400 
401  while ((stop_monitor != true) && (g_wpa_monitor != NULL)) {
402  if (wpa_ctrl_pending(g_wpa_monitor) > 0) {
403 
404  memset(event_buf, 0, sizeof(event_buf));
405  event_buf_len = sizeof(event_buf) - 1;
406 
407  if (0 == wpa_ctrl_recv(g_wpa_monitor, event_buf, &event_buf_len)) {
408 
409  WIFI_LOG_DEBUG( "%s: wpa_ctrl_recv got event_buf = [%s]\n", __FUNCTION__, event_buf);
410 
411  start = strchr(event_buf, '>');
412  if (start == NULL) continue;
413  if ((strstr(start, WPA_EVENT_SCAN_STARTED) != NULL)&&(!bNoAutoScan)) {
414 
415  // example event_buffer for WPA_EVENT_SCAN_STARTED:
416  // "<3>CTRL-EVENT-SCAN-STARTED "
417  // does not contain explicit information on the SSID for which "scan started"
418  // so get it from previously saved info (ssid_to_find), or by other means ("GET_NETWORK 0 ssid")
419 
420  WIFI_LOG_INFO("Scan started \n");
421 
422  if (!*ssid_to_find)
423  {
424  WIFI_LOG_INFO("ssid_to_find empty. Issuing 'GET_NETWORK 0 ssid' to get SSID being scanned for\n");
425  pthread_mutex_lock(&wpa_sup_lock);
426  wpaCtrlSendCmd("GET_NETWORK 0 ssid");
427  const char* ptr_start_quote = strchr (return_buf, '"'); // locate quote before SSID
428  char* ptr_end_quote = NULL; // reverse search to locate quote after SSID
429  if (ptr_start_quote && (ptr_end_quote = strrchr (ptr_start_quote, '"')) > ptr_start_quote)
430  {
431  *ptr_end_quote = '\0'; // replace quote after SSID with '\0'
432  strcpy (ssid_to_find, ptr_start_quote + 1);
433  }
434  pthread_mutex_unlock(&wpa_sup_lock);
435  WIFI_LOG_INFO("ssid based on network id = [%s] \n", return_buf);
436  }
437  WIFI_LOG_INFO("SSID to find = [%s] \n", ssid_to_find);
438  strcpy(scanned_ssid, ssid_to_find);
439 
440  pthread_mutex_lock(&wpa_sup_lock);
441 
442  /* Flush the BSS every time so that there is no stale information */
443  WIFI_LOG_INFO("Flushing the BSS now\n");
444  wpaCtrlSendCmd("BSS_FLUSH 0");
445 
446  cur_scan_state = WIFI_HAL_WPA_SUP_SCAN_STATE_STARTED;
447  pthread_mutex_unlock(&wpa_sup_lock);
448  }
449 
450  else if (strstr(start, WPA_EVENT_SCAN_RESULTS) != NULL) {
451  WIFI_LOG_INFO("Scan results received \n");
452  if (!bNoAutoScan)
453  {
454  pthread_mutex_lock(&wpa_sup_lock);
455  return_buf[0] = '\0';
456  wpaCtrlSendCmd("SCAN_RESULTS");
457  log_top5_bssids(return_buf);
458  if (*ssid_to_find)
459  {
460  WIFI_LOG_INFO("Buffer Length = %lu \n",strlen(return_buf));
461  ap_count = parse_scan_results (return_buf, strlen (return_buf));
462  if (!find_ssid_in_scan_results (ssid_to_find))
463  WIFI_LOG_ERROR("SSID [%s] not found in scan results\n", ssid_to_find);
464  }
465  else
466  {
467  WIFI_LOG_ERROR("no SSID to find\n");
468  }
469  pthread_mutex_unlock(&wpa_sup_lock);
470  }
471  else
472  {
473  WIFI_LOG_INFO("Application is running wifi scan so skipping \n");
474  }
475  if (cur_scan_state == WIFI_HAL_WPA_SUP_SCAN_STATE_STARTED) {
476  pthread_mutex_lock(&wpa_sup_lock);
477  cur_scan_state = WIFI_HAL_WPA_SUP_SCAN_STATE_RESULTS_RECEIVED;
478  pthread_mutex_unlock(&wpa_sup_lock);
479  }
480  }
481 
482  else if((strstr(start, WPS_EVENT_AP_AVAILABLE_PBC) != NULL)) {
483  WIFI_LOG_INFO("WPS Connection in progress\n");
484  connError = WIFI_HAL_CONNECTING;
485  /* Trigger callback to Network Service Manager */
486  if (callback_connect) (*callback_connect)(1, current_ssid, &connError);
487  }
488 
489  else if(strstr(start, WPS_EVENT_TIMEOUT) != NULL) {
490  WIFI_LOG_INFO("WPS Connection timeout\n");
491  bIsWpsCompleted = TRUE;
492  connError = WIFI_HAL_ERROR_NOT_FOUND;
493  if (callback_disconnect) (*callback_disconnect)(1, "", &connError);
494  }
495  /* Adding WPS Overlap Detection Events , This happens when an enrollee detects two registrars with PBC session
496  active.*/
497  else if(strstr(start,WPS_EVENT_OVERLAP) != NULL) {
498  WIFI_LOG_ERROR("WPS Overlap detected. ! Canceling WPS Operation...\n");
499  bIsPBCOverlapDetected = TRUE;
500  // TODO - wpa_supplicant deafult behaviour is cancel wps operation so cancelling for now
501  if(isDualBandSupported()) // For Xi6
502  stop_wifi_wps_connection();
503  else { // For Xi5
504  WIFI_LOG_ERROR("TELEMETRY_WPS_CONNECTION_STATUS:DISCONNECTED,WPS_PBC_OVERLAP \n");
505  connError = WIFI_HAL_ERROR_NOT_FOUND;
506  if (callback_disconnect) (*callback_disconnect)(1, "", &connError);
507  }
508  bIsWpsCompleted = TRUE;
509  }
510 
511  else if(strstr(start, WPS_EVENT_SUCCESS) != NULL) {
512  bIsWpsCompleted = TRUE;
513  bNoAutoScan = FALSE;//Setting bNoAutoScan as FALSE since WPS is successful
514  WIFI_LOG_INFO("WPS is successful...Associating now\n");
515  }
516 
517  else if(strstr(start, WPA_EVENT_CONNECTED) != NULL) {
518  WIFI_LOG_INFO("Authentication completed successfully and data connection enabled\n");
519 
520  pthread_mutex_lock(&wpa_sup_lock);
521  /* Save the configuration */
522  if(isPrivateSSID){
523  wpaCtrlSendCmd("SAVE_CONFIG");
524  bUpdatedSSIDInfo=1;
525  WIFI_LOG_INFO("[%s:%d] Configuration Saved \n",__FUNCTION__,__LINE__);
526  }
527 
528  int retStatus = wpaCtrlSendCmd("STATUS");
529  if (retStatus == -2)
530  telemetry_event_d("WIFIV_WARN_hal_timeout", 1);
531  int rc = snprintf (tmp_return_buf, sizeof(tmp_return_buf), "%s", return_buf);
532  if(rc < 0)
533  WIFI_LOG_ERROR("snprintf of tmp_return_buf failed\n");
534 
535  const char* bssid_ptr = getValue(return_buf, "bssid");
536  const char *ptr;
537  if (bssid_ptr)
538  {
539  snprintf (current_bssid, sizeof(current_bssid), "%s", bssid_ptr);
540  ptr = bssid_ptr + strlen(bssid_ptr) + 1;
541  }
542  else
543  {
544  WIFI_LOG_ERROR( "BSSID is NULL. Status output = [%s]\n", tmp_return_buf);
545  current_bssid[0] = '\0';
546  ptr = return_buf;
547  }
548  const char *ssid_ptr = getValue(ptr, "ssid");
549  printf_decode ((u8*)current_ssid, sizeof(current_ssid), ssid_ptr ? ssid_ptr : "");
550  WIFI_LOG_INFO("Connected to BSSID [%s], SSID [%s]\n", current_bssid, current_ssid);
551  pthread_mutex_unlock(&wpa_sup_lock);
552 
553  /* Clear the out of range SSID as there is an user intervention */
554  if(*out_of_range_ssid)
555  {
556  *out_of_range_ssid = 0;
557  WIFI_LOG_INFO("Out of range SSID : %s\n", out_of_range_ssid);
558  }
559 
560  connError = WIFI_HAL_SUCCESS;
561 
562  //pthread_mutex_lock(&wpa_sup_lock);
563  /* Save the BSSID in the configuration file */
564 // sprintf(cmd_buf, "SET_NETWORK 0 bssid %s",curr_bssid);
565 // wpaCtrlSendCmd(cmd_buf);
566 
567  /* Do not store the PSK in the config file */
568  //wpaCtrlSendCmd("SET_NETWORK 0 mem_only_psk 1");
569 
570  //pthread_mutex_unlock(&wpa_sup_lock);
571  /* Trigger callback to Network Service Manager */
572  if (callback_connect) (*callback_connect)(1, current_ssid, &connError);
573  }
574 
575  else if(strstr(start, WPA_EVENT_DISCONNECTED) != NULL) {
576 
577  // example event_buffer for WPA_EVENT_DISCONNECTED:
578  // "<3>CTRL-EVENT-DISCONNECTED bssid=5c:b0:66:00:4d:10 reason=8"
579 
580  char* name_value_entry = NULL;
581  strtok_r (start, " ", &saveptr); // skip past the "CTRL-EVENT-DISCONNECTED" in the event_buffer
582  while (NULL != (name_value_entry = strtok_r (NULL, " ", &saveptr)))
583  {
584  if (0 == strncmp (name_value_entry, "bssid=", strlen ("bssid=")))
585  snprintf (last_disconnected_bssid, sizeof(last_disconnected_bssid), "%s", name_value_entry + strlen ("bssid="));
586  else if (0 == strncmp (name_value_entry, "reason=", strlen ("reason=")))
587  last_disconnected_reason_code = atoi (name_value_entry + strlen ("reason="));
588  }
589 
590  // Clear the out of range SSID on receiving the WPA_EVENT_DISCONNECTED event only if the
591  // disconnect is received from the router with reason code != PREVIOUS_AUTH_INVALID (i.e if reason_code!=2)
592  // and if there was a router reboot (i.e if out_of_range_ssid is populated)
593  if( *out_of_range_ssid && (last_disconnected_reason_code != PREVIOUS_AUTH_INVALID) )
594  {
595  *out_of_range_ssid = 0;
596  WIFI_LOG_INFO("Out of range SSID : %s\n", out_of_range_ssid);
597  }
598 
599  // if current_bssid = last_disconnected_bssid, assume last_disconnected_ssid = current_ssid; else reset last_disconnected_ssid
600  snprintf (last_disconnected_ssid, sizeof(last_disconnected_ssid), "%s",
601  0 == strcasecmp (current_bssid, last_disconnected_bssid) ? current_ssid : "");
602 
603  WIFI_LOG_INFO(
604  "Disconnected from BSSID [%s], reason_code [%d] (SSID [%s]), last successfully connected bssid [%s]\n",
605  last_disconnected_bssid, last_disconnected_reason_code, last_disconnected_ssid, current_bssid);
606 
607  // set current BSSID and SSID to empty as we just disconnected
608  current_bssid[0] = '\0';
609  current_ssid[0] = '\0';
610 
611  connError = WIFI_HAL_SUCCESS;
612 #ifdef WIFI_CLIENT_ROAMING
613  // Disable if any in progress Roaming
614  if( cur_roaming_state == WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_STARTED) {
615  pthread_cond_signal(&cond);
616  }
617  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Connection state changed, Refresh backoff
618  backOffRefreshed = 1;
619 #endif
620  if (callback_disconnect) (*callback_disconnect)(1, last_disconnected_ssid, &connError);
621  }
622 
623  else if (strstr (start, WPA_EVENT_TEMP_DISABLED) != NULL) {
624 
625  // example event_buffer for WPA_EVENT_TEMP_DISABLED:
626  // "<3>CTRL-EVENT-SSID-TEMP-DISABLED id=0 ssid="D375C1D9F8B041E2A1995B784064977B" auth_failures=1 duration=10 reason=AUTH_FAILED"
627  // holds an SSID encoded by wpa_supplicant's printf_encode function, so we need to printf_decode this
628 
629  connError = WIFI_HAL_ERROR_CONNECTION_FAILED; // default value
630 
631  char ssid[MAX_SSID_LEN+1] = "<UNKNOWN>";
632  int duration = -1;
633  int auth_failures = -1;
634  char reason[128] = "UNKNOWN";
635 
636  const char* ptr_start_quote = strchr (start, '"'); // locate quote before SSID
637  char* ptr_end_quote = NULL; // reverse search to locate quote after SSID
638  if (ptr_start_quote && (ptr_end_quote = strrchr (ptr_start_quote, '"')) > ptr_start_quote)
639  {
640  *ptr_end_quote = '\0'; // replace quote after SSID with '\0' so printf_decode can work
641  printf_decode ((u8*)ssid, sizeof(ssid), ptr_start_quote + 1);
642  *ptr_end_quote = '"'; // put back the quote after SSID so search for other fields can work
643 
644  // search for other fields after ssid field
645  char* name_value_entry = NULL;
646  strtok_r (ptr_end_quote, " ", &saveptr);
647  while (NULL != (name_value_entry = strtok_r (NULL, " ", &saveptr)))
648  {
649  if (0 == strncmp (name_value_entry, "auth_failures=", strlen ("auth_failures=")))
650  auth_failures = atoi (name_value_entry + strlen ("auth_failures="));
651  else if (0 == strncmp (name_value_entry, "duration=", strlen ("duration=")))
652  duration = atoi (name_value_entry + strlen ("duration="));
653  else if (0 == strncmp (name_value_entry, "reason=", strlen ("reason=")))
654  snprintf (reason, sizeof (reason), "%s", name_value_entry + strlen ("reason="));
655  }
656 
657  if (0 == strcmp (reason, "WRONG_KEY")) {
659  } else if (0 == strcmp (reason, "AUTH_FAILED"))
660  connError = WIFI_HAL_ERROR_AUTH_FAILED;
661  }
662 
663  WIFI_LOG_INFO( "SSID [%s] disabled for %ds (auth_failures=%d), reason=%s, connError [%d]\n",
664  ssid, duration, auth_failures, reason, connError);
665 
666  /* If the user enters the wrong credentials and connect_withSSID() API is called,
667  * then disconnect the device from the router */
668  /* If router is rebooted, then do not send the DISCONNECT command to the wpa supplicant
669  * and instead continue with the wpa_supplicant scan for SSID */
670  if(connError == WIFI_HAL_ERROR_INVALID_CREDENTIALS)
671  {
672  if(strlen(out_of_range_ssid) > 0)
673  {
674  /* In case of router reboot, do not send the notification to the application
675  * by calling the callback_connect() function and do not send DISCONNECT to wpa supplicant
676  * out_of_range_ssid holds the SSID of the router that was rebooted/out of range */
677  continue;
678  }
679  else
680  {
681  WIFI_LOG_INFO( "Connection failed due to invalid credential, Disconnecting...\n");
682  pthread_mutex_lock(&wpa_sup_lock);
683  wpaCtrlSendCmd("DISCONNECT");
684  pthread_mutex_unlock(&wpa_sup_lock);
685  }
686  }
687 
688  if (callback_connect)
689  (*callback_connect) (1, ssid, &connError);
690  }
691 
692  else if (strstr (start, WPA_EVENT_REENABLED) != NULL) {
693 
694  // example event_buffer for WPA_EVENT_REENABLED:
695  // <3>CTRL-EVENT-SSID-REENABLED id=0 ssid="124ABCDEF!@#$%^&*()_+}{\\\":?><-"
696  // holds an SSID encoded by wpa_supplicant's printf_encode function, so we need to printf_decode this
697 
698  char ssid[MAX_SSID_LEN+1] = "<UNKNOWN>";
699 
700  const char* ptr_start_quote = strchr (start, '"'); // locate quote before SSID
701  char* ptr_end_quote = NULL; // reverse search to locate quote after SSID
702  if (ptr_start_quote && (ptr_end_quote = strrchr (ptr_start_quote, '"')) > ptr_start_quote)
703  {
704  *ptr_end_quote = '\0'; // replace quote after SSID with '\0' so printf_decode can work
705  printf_decode ((u8*)ssid, sizeof(ssid), ptr_start_quote + 1);
706  *ptr_end_quote = '"'; // put back the quote after SSID so search for other fields can work
707  }
708 
709  WIFI_LOG_INFO( "SSID [%s] re-enabled\n", ssid);
710  }
711 
712  else if((strstr(start, WPA_EVENT_NETWORK_NOT_FOUND) != NULL)&&(!bNoAutoScan)) {
713  // if WPA_EVENT_NETWORK_NOT_FOUND arrives, it means the network/SSID that was last scanned for was not found
714  // (btw, we would have already learnt this on receipt of WPA_EVENT_SCAN_RESULTS (in 'find_ssid_in_scan_results')
715  // as events arrive in the order: WPA_EVENT_SCAN_STARTED, WPA_EVENT_SCAN_RESULTS, WPA_EVENT_NETWORK_NOT_FOUND)
716 
717  // example event_buffer for WPA_EVENT_NETWORK_NOT_FOUND:
718  // "<3>CTRL-EVENT-NETWORK-NOT-FOUND "
719  // does not contain explicit information on the SSID that was "not found"
720  // but the SSID that was "not found" is the SSID that was last scanned for (for which we got the last WPA_EVENT_SCAN_STARTED)
721 
722  WIFI_LOG_INFO("SSID [%s] not found in last scan\n", ssid_to_find);
723  connError = WIFI_HAL_ERROR_NOT_FOUND;
724 
725  // if a WPS_CANCEL command is sent to wpa_supplicant when it is in a SCANNING state,
726  // it triggers a NETWORK_NOT_FOUND event; which we should ignore (or suffer XIONE-9407)
727  // TODO: revisit logic with wpa_supplicant v2.10+ (introduces WPS_EVENT_CANCEL on WPS_CANCEL)
728  struct timespec now;
729  clock_gettime(CLOCK_MONOTONIC, &now);
730  if (timespec_diff_ms(&timespec_wps_cancel, &now) < 1000)
731  {
732  WIFI_LOG_WARN("Ignoring NETWORK_NOT_FOUND event received within 1s of WPS_CANCEL \n");
733  continue;
734  }
735 
736  // extra logic to check if an SSID change is the cause of the "network not found"
737  // if currently disconnected (no current ssid) and last disconnect was from the SSID for which we just got a "not found"
738  if (!*current_ssid && *last_disconnected_ssid && (0 == strcmp (last_disconnected_ssid, ssid_to_find)))
739  {
740  // check if the BSS we were connected to was heard from in last scan
741  // if the BSS is still alive, its SSID must have changed as we just got a "not found" for its previous SSID
742  if (*last_disconnected_bssid)
743  {
744  pthread_mutex_lock(&wpa_sup_lock);
745  snprintf(cmd_buf, sizeof(cmd_buf), "BSS %s", last_disconnected_bssid);
746  wpaCtrlSendCmd(cmd_buf);
747  WIFI_LOG_TRACE("cmd_buf = [%s], return_buf = [%s]\n", cmd_buf, return_buf);
748  if (*return_buf) {
749  WIFI_LOG_INFO("BSSID [%s] had an SSID change\n", last_disconnected_bssid);
750  connError = WIFI_HAL_ERROR_SSID_CHANGED;
751  }
752  else {
753  WIFI_LOG_INFO("BSSID [%s] is down or not within range\n", last_disconnected_bssid);
754 
755  /* We enter this condition if the router is out of range/rebooted.
756  * If the router SSID is out of range, then set the out of range SSID */
757  strcpy(out_of_range_ssid, last_disconnected_ssid);
758  WIFI_LOG_INFO("Out of range SSID : %s\n", out_of_range_ssid);
759  }
760  pthread_mutex_unlock(&wpa_sup_lock);
761  }
762  }
763  if ((WIFI_HAL_ERROR_NOT_FOUND == connError) && (0 != strcmp (ssid_to_find, scanned_ssid)) && isPrivateSSID)
764  {
765  // Hidden SSIDs will be listed in scan results only if a scan probe request is being initiated from supplicant.
766  // Scan results is valid for 5s. In this gap, if a new connect request for hidden ssid comes,
767  // supplicant checks this new SSID in previoulsy scanned list and detect as AP not found.
768  // Here we are skipping this no ssid found error as a scan is not yet performed for the SSID to find.
769  WIFI_LOG_INFO("Skipping no ssid found error: Scanned SSID = [%s] SSID to find = [%s]", scanned_ssid, ssid_to_find);
770  continue;
771  }
772  if (callback_disconnect) (*callback_disconnect)(1, ssid_to_find, &connError);
773  } /* WPA_EVENT_NETWORK_NOT_FOUND */
774 #ifdef WIFI_CLIENT_ROAMING
775  else if((strstr(start, WPA_EVENT_SIGNAL_CHANGE) != NULL) && isPrivateSSID) {
776  // RSSI Signal Threshold change detected for private SSID.
777  // Sample Event : <3>CTRL-EVENT-SIGNAL-CHANGE above=1 signal=-15 noise=-110 txrate=6000
778  // <3>CTRL-EVENT-SIGNAL-CHANGE above=0 signal=-68 noise=-110 txrate=6000
779  // TODO :- Check if associated, Check state is connected
780  WIFI_LOG_DEBUG("RSSI Change event detected, Event = %s \n",start);
781  // Check If Roaming is enabled or not
782  if(pstRoamingCtrl.roamingEnable == true) {
783  int rssi=0,isAbove=0,readCount=0;
784  // Skip CTRL-EVENT-SIGNAL-CHANGE tags
785  char *eventData = strstr(start," ");
786  readCount = sscanf(eventData," above=%d signal=%d",&isAbove,&rssi);
787  if(readCount == 2) {
788  WIFI_LOG_DEBUG("Signal Change event received with RSSI=[%d] and isAbove=[%d] \n",rssi,isAbove);
789  if(isAbove == 0 && cur_roaming_state == WIFI_HAL_ROAM_STATE_ROAMING_IDLE) { // RSSI is below threshold , Trigger romaing timer
790  cur_roaming_state = WIFI_HAL_ROAM_STATE_SIGNAL_PROCESSING;
791  int time = 0;
792  if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_SELF_STEERING)
793  time = pstRoamingCtrl.postAssnSelfSteerTimeframe;
794  else if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_AP_STEERING)
795  time = pstRoamingCtrl.postAssnAPctrlTimeframe;
796  pthread_create(&wifi_signal_mon_thread,NULL,start_wifi_signal_monitor_timer, (void*)time);
797  } else if(isAbove == 1 && cur_roaming_state == WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_STARTED){
798  WIFI_LOG_INFO("Signal strength is recovered, Stopping Roaming timer.\n");
799  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Roaming Disabled, Refresh backoff
800  backOffRefreshed = 1;
801  pthread_cond_signal(&cond);
802  } else if(cur_roaming_state != WIFI_HAL_ROAM_STATE_ROAMING_IDLE){
803  WIFI_LOG_DEBUG("Roaming is in progres, Skipping signal change event \n");
804  }
805  } else {
806  WIFI_LOG_ERROR("Failed to parse signal change event. \n");
807  }
808  }
809  else {
810  WIFI_LOG_DEBUG("Skipping signal change event, Roaming is disabled.\n");
811  }
812  }
813  else if((strstr(start, RRM_EVENT_NEIGHBOR_REP_RXED) != NULL))
814  {
815  WIFI_LOG_INFO("RRM Neighbor report received event\n");
816  if(pstRoamingCtrl.roamingEnable && pstRoamingCtrl.roam80211kvrEnable) {
817  cur_roaming_mode = WIFI_HAL_ROAMING_MODE_AP_STEERING;
818  int ret = parse_neighbor_report_response(start,&stRrmNeighborRpt);
819  if(ret != RETURN_OK)
820  cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_STATE_INTERNAL_ERROR;
821  else
822  cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_RECEIVED;
823  } else {
824  WIFI_LOG_DEBUG("RRM Skipping neighbor report, Roaming/KVR is disabled.\n");
825  }
826  } else if ((strstr(start, RRM_EVENT_NEIGHBOR_REP_FAILED) != NULL)) {
827  WIFI_LOG_INFO("RRM Neighbor report failed event. \n");
828  cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_REQUEST_FAILED;
829  }
830  else if(strstr(start,WPA_EVENT_BEACON_LOSS) != NULL)
831  {
832  WIFI_LOG_INFO("Beacon Loss event detected. Client may disconnect.\n");
833  telemetry_event_d("WIFIV_WARN_BcnLossdisconn", 1);
834  } else if(strstr(start,"WNM-BTM-REQ-RECEIVED") != NULL)
835  {
836  WIFI_LOG_INFO("WNM- BTM Request Received. \n");
837  } else if(strstr(start,"WNM-BTM-RES-SENT") != NULL) {
838  WIFI_LOG_INFO("WNM- BTM Response Sent. \n");
839  cur_roaming_mode = WIFI_HAL_ROAMING_MODE_AP_STEERING;
840  } else if(strstr(start, WPA_EVENT_AUTH_REJECT) != NULL ||
841  strstr(start, WPA_EVENT_ASSOC_REJECT) != NULL) {
842  /* Clear the out of range SSID as there is an user intervention */
843  if(*out_of_range_ssid)
844  {
845  *out_of_range_ssid = 0;
846  WIFI_LOG_INFO("Out of range SSID : %s\n", out_of_range_ssid);
847  }
848  }
849 #endif // WIFI_CLIENT_ROAMING
850  else {
851  continue;
852  }
853  }
854  }
855  else {
856  usleep(WPA_SUP_TIMEOUT);
857  }
858  } /* End while loop */
859  return NULL;
860 } /* End monitor_thread function */
861 
862 
863 /**************************************************************************************************/
864 /*WIFI WPS Related Functions */
865 /**************************************************************************************************/
866 
867 INT wifi_getCliWpsEnable(INT ssidIndex, BOOL *output_bool){
868  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
869  return RETURN_OK;
870 }
871 
872 INT wifi_setCliWpsEnable(INT ssidIndex, BOOL enableValue){
873  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
874  return RETURN_OK;
875 }
876 
877 INT wifi_getCliWpsDevicePIN(INT ssidIndex, ULONG *output_ulong){ //Where does the PIN come from?
878  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
879  return RETURN_OK;
880 }
881 
882 INT wifi_setCliWpsDevicePIN(INT ssidIndex, ULONG pin){
883 #if 0
884  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID:%d\n", ssidIndex);
885  uint32_t wps_pin = 0;
886  if(NetAppWiFiGenerateWPSPin(hNetApp, &wps_pin) == NETAPP_SUCCESS){ //Trying to generate the pin and checking if the result is a success
887  pin = wps_pin;
888  return RETURN_OK;
889  }
890  WIFI_LOG_INFO("Error setting the device pin\n");
891  return RETURN_ERR;
892 #endif
893 return RETURN_OK;
894 }
895 
896 INT wifi_getCliWpsConfigMethodsSupported(INT ssidIndex, CHAR *methods){
897 
898  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
899  //Return all the methods: Push and Pin
900 
901  if (!is_null_pointer(methods)){
902  strcpy(methods, "Push and Pin");
903  WIFI_LOG_INFO("Supported Methods: Push and Pin\n");
904  return RETURN_OK;
905  }
906  return RETURN_ERR;
907 }
908 
909 INT wifi_getCliWpsConfigMethodsEnabled(INT ssidIndex, CHAR *output_string){
910 
911  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
912  //I think returning push and pin for this would be acceptable
913  if (!is_null_pointer(output_string)){
914  strcpy(output_string, "Push and Pull");
915  return RETURN_OK;
916  }
917  return RETURN_ERR;
918 }
919 
920 INT wifi_setCliWpsConfigMethodsEnabled(INT ssidIndex, CHAR *methodString){
921 
922  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
923  if (!is_null_pointer(methodString)){
924  strcpy(methodString, "Push and Pin");
925  WIFI_LOG_INFO("Supported Methods: Push and Pin\n");
926  return RETURN_OK;
927  }
928  return RETURN_ERR;
929 }
930 
931 INT wifi_getCliWpsConfigurationState(INT ssidIndex, CHAR *output_string){
932 
933  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
934  return RETURN_OK;
935 }
936 
937 INT wifi_setCliWpsEnrolleePin(INT ssidIndex, CHAR *wps_pin){
938 
939  WIFI_LOG_INFO("WPS Pin Call\n");
940 
941  WIFI_LOG_DEBUG("wps_pin = %s\n", wps_pin);
942 
943  bool command_failed;
944 
945  if (wps_pin == NULL || *wps_pin == '\0') // NOTE: remove " || *wps_pin == '\0'" to allow PIN auto-generation
946  {
947  WIFI_LOG_ERROR("No PIN supplied.\n");
948  return RETURN_ERR;
949  }
950 
951  if (*wps_pin) // if PIN is supplied, validate it
952  {
953  pthread_mutex_lock(&wpa_sup_lock);
954  sprintf(cmd_buf, "WPS_CHECK_PIN %s", wps_pin);
955  // on success, return_buf contains supplied PIN.
956  // on failure, return_buf contains "FAIL" if PIN is not 8 digits, "FAIL-CHECKSUM" otherwise (last digit != checksum of first 7 digits).
957  command_failed = true;
958  if (0 == wpaCtrlSendCmd(cmd_buf))
959  {
960  if (strncmp(return_buf, "FAIL", 4) == 0)
961  WIFI_LOG_ERROR("command '%s' returned '%s'\n", cmd_buf, return_buf);
962  else
963  command_failed = false;
964  }
965  pthread_mutex_unlock(&wpa_sup_lock);
966  if (command_failed)
967  return RETURN_ERR;
968  }
969 
970  pthread_mutex_lock(&wpa_sup_lock);
971  if (cur_sup_state != WIFI_HAL_WPA_SUP_STATE_IDLE)
972  {
973  pthread_mutex_unlock(&wpa_sup_lock);
974  WIFI_LOG_INFO("Connection is in progress, returning error \n");
975  return RETURN_ERR;
976  }
977 
978  isPrivateSSID = 1;
979  wpaCtrlSendCmd("REMOVE_NETWORK 0");
980  wpaCtrlSendCmd("SAVE_CONFIG");
981  bUpdatedSSIDInfo = 1;
982 
983  //Trigger wps_pin
984  bIsWpsCompleted = FALSE;
985  sprintf(cmd_buf, "WPS_PIN any"); // the "any" is case-sensitive ("ANY" does not work)
986  if (*wps_pin)
987  {
988  strcat(cmd_buf, " ");
989  strcat(cmd_buf, wps_pin);
990  }
991  // on success, return_buf contains the PIN used for WPS negotiation with AP
992  // on failure, return_buf starts with "FAIL..."
993  command_failed = true;
994  if (0 == wpaCtrlSendCmd(cmd_buf))
995  {
996  if (strncmp(return_buf, "FAIL", 4) == 0)
997  WIFI_LOG_ERROR("command '%s' returned '%s'\n", cmd_buf, return_buf);
998  else
999  {
1000  command_failed = false;
1001  if (*wps_pin == '\0')
1002  strncat (wps_pin, return_buf, 8); // copy auto-generated PIN from return_buf into wps_pin
1003  }
1004  }
1005  pthread_mutex_unlock(&wpa_sup_lock);
1006  if (command_failed)
1007  return RETURN_ERR;
1008 
1009  WIFI_LOG_INFO("Will be timing out if AP is not found after 120 seconds\n");
1010 
1011  if (false == wpa_supplicant_conf_reset())
1012  return RETURN_ERR;
1013 
1015  (*callback_connect)(1, "", &connError);
1016  WIFI_LOG_INFO("Connection in progress..\n");
1017 
1018  #if 0
1019  INT* pinValue = 0;
1020  *pinValue = atoi(EnrolleePin);
1021  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
1022  if(NetAppWiFiConnectByPin(hNetApp, NETAPP_IFACE_WIRELESS, NULL, *pinValue, true) == NETAPP_SUCCESS){ //Connecting to the device using a pin and checking the result
1023  return RETURN_OK;
1024  }
1025  WIFI_LOG_INFO("Error connecting to device with enrollee pin... Check again\n");
1026  return RETURN_ERR;
1027 #endif
1028  return RETURN_OK;
1029 }
1030 
1031 // Parse Scan results and fetch all WPS-PBC enabled accesspoints
1032 int parse_wps_pbc_accesspoints(char *buf,wifi_wps_pbc_ap_t ap_list[])
1033 {
1034  char *ptr = NULL;
1035  char *saveptr = NULL;
1036  char ssid[MAX_SSID_LEN+1];
1037  char bssid[32];
1038  char rssi[8];
1039  char freq[8];
1040  int apCount = 0;
1041  char *eptr = NULL;
1042 
1043  //Memset arrays
1044  memset(ssid,0,sizeof(ssid));
1045  memset(bssid,0,sizeof(bssid));
1046  memset(rssi,0,sizeof(rssi));
1047  memset(freq,0,sizeof(freq));
1048 
1049  /* skip heading */
1050  ptr = strstr(buf,"/ ssid");
1051  if (ptr == NULL) return -1;
1052  ptr += strlen("/ ssid") + 1;
1053 
1054  char* line = strtok_r(ptr, "\n", &saveptr);
1055  while(line != NULL && apCount < MAX_WPS_AP_COUNT)
1056  {
1057  if(strstr(line,"[WPS-PBC]") != NULL)
1058  {
1059  ssid[0] = '\0';
1060  bssid[0] = '\0';
1061  rssi[0] = '\0';
1062  freq[0] = '\0';
1063  sscanf(line,"%32s %5s %7s %*s %32s",bssid,freq,rssi,ssid);
1064  if((ssid[0] != '\0') && (bssid[0] != '\0') && (rssi[0] != '\0') && (freq[0] != '\0'))
1065  {
1066  WIFI_LOG_INFO("WPS-PBC AccessPoint[%d] : [SSID = %s , BSSID = %s , FREQ = %s , RSSI = %s ]\n",apCount,ssid,bssid,freq,rssi);
1067  strncpy(ap_list[apCount].ap_BSSID,bssid,sizeof(ap_list[apCount].ap_BSSID));
1068  strncpy(ap_list[apCount].ap_SSID,ssid,sizeof(ap_list[apCount].ap_SSID));
1069  ap_list[apCount].ap_Frequency = (int) strtol(freq,&eptr,10);
1070  ap_list[apCount].ap_FreqBand = (((ap_list[apCount].ap_Frequency/1000) == 5)?WIFI_HAL_FREQ_BAND_5GHZ:WIFI_HAL_FREQ_BAND_24GHZ);
1071  ap_list[apCount].ap_SignalStrength = (int) strtol(rssi,&eptr,10);
1072  apCount++;
1073  }
1074  }
1075  line = strtok_r(NULL, "\n", &saveptr);
1076  }
1077  return apCount;
1078 }
1079 
1080 // Cancel WPS Pairing Operation
1081 INT wifi_cancelWpsPairing ()
1082 {
1083  int retStatus = RETURN_ERR;
1084 
1085  // Check for any inprogress WPS operation
1086  if(bIsWpsCompleted == FALSE)
1087  {
1088  stop_wifi_wps_connection();
1089  retStatus = RETURN_OK;
1090  }
1091  else
1092  {
1093  WIFI_LOG_INFO("No In-Progress WPS Operation, Skipping WPS_CANCEL. \n");
1094  }
1095  return retStatus;
1096 }
1097 
1098 
1099 // Cancel the WPS operation
1100 void stop_wifi_wps_connection()
1101 {
1102  bNoAutoScan = FALSE;//Setting bNoAutoScan as FALSE since WPS fails
1103  if(bIsWpsCompleted == FALSE)
1104  {
1105  WIFI_LOG_INFO("Stopping WPS operation.. \n");
1106  if (bWpsPBC && isDualBandSupported())
1107  pthread_cancel(wps_start_thread); // Lets forcefully stop the thread as we need to strictly maintain WPS time frame
1108 
1109  // Make sure that the mutex is not locked by wps thread & Cancel WPS operation
1110  if(pthread_mutex_trylock(&wpa_sup_lock) != 0)
1111  {
1112  pthread_mutex_unlock(&wpa_sup_lock);
1113  pthread_mutex_lock(&wpa_sup_lock);
1114  }
1115  clock_gettime(CLOCK_MONOTONIC, &timespec_wps_cancel);
1116  wpaCtrlSendCmd("WPS_CANCEL");
1117  // Abort scanning if any scanning is in progress
1118  if(cur_scan_state != WIFI_HAL_WPA_SUP_SCAN_STATE_IDLE)
1119  wpaCtrlSendCmd("ABORT_SCAN");
1120  pthread_mutex_unlock(&wpa_sup_lock);
1121 
1122  // Inform netsrvmgr that WPS is failed and status is disconnected.
1123  wifiStatusCode_t connError;
1124  connError = WIFI_HAL_ERROR_NOT_FOUND;
1125  if (callback_disconnect) (*callback_disconnect)(1, "", &connError);
1126  if(bIsPBCOverlapDetected == TRUE)
1127  WIFI_LOG_INFO("TELEMETRY_WPS_CONNECTION_STATUS:DISCONNECTED,WPS_PBC_OVERLAP\n");
1128  else
1129  WIFI_LOG_INFO("TELEMETRY_WPS_CONNECTION_STATUS:DISCONNECTED,WPS_TIME_OUT\n");
1130  bIsWpsCompleted = TRUE;
1131  }
1132 }
1133 
1134 // Check wether the station has dual band support
1135 BOOL isDualBandSupported()
1136 {
1137  FILE *fp = NULL;
1138  char cmd[BUFF_LEN_64];
1139  char result[BUFF_LEN_64];
1140  bool retStatus = false;
1141 
1142  memset(cmd,0,sizeof(cmd));
1143  memset(result,0,BUFF_LEN_64);
1144 
1145  snprintf(cmd,sizeof(cmd),"iw list | grep 'Band' | tr '\n' ' '");
1146  fp = popen(cmd,"r");
1147  if (fp != NULL)
1148  {
1149  if ((fgets(result, sizeof(result), fp) != NULL) && (result[0] != '\0'))
1150  {
1151  if((strstr(result,"Band 1:") != NULL) && (strstr(result,"Band 2:") != NULL))
1152  {
1153  // Dual Band since both Band 1 and Band 2 capabilties are present in iw list
1154  retStatus = true;
1155  }
1156  else
1157  {
1158  retStatus = false;
1159  }
1160  }
1161  pclose(fp);
1162  }
1163  else
1164  {
1165  WIFI_LOG_ERROR("isDualBandSupported() : popen() failed \n");
1166  }
1167  return retStatus;
1168 }
1169 
1170 // Initiate WPS connection to athe given BSSID
1171 int triggerWpsPush(char *bssid)
1172 {
1173  char cmd[32];
1174  int retStatus = -1;
1175 
1176  if(bssid != NULL)
1177  {
1178  memset(cmd,0,sizeof(cmd));
1179  snprintf(cmd,32,"WPS_PBC %s",bssid);
1180  WIFI_LOG_INFO("Initiating WPS connection to BSSID - %s \n",bssid );
1181  pthread_mutex_lock(&wpa_sup_lock);
1182  retStatus = wpaCtrlSendCmd(cmd);
1183  pthread_mutex_unlock(&wpa_sup_lock);
1184  }
1185  else
1186  {
1187  WIFI_LOG_ERROR("triggerWpsPush() failed , BSSID is NULL.! \n");
1188  }
1189  return retStatus;
1190 }
1191 
1192 // Start WPS operation with Band selection.
1193 void* start_wifi_wps_connection(void *param)
1194 {
1195  int apCount = 0;
1196  int i = 0;
1197  wifi_wps_pbc_ap_t ap_list[MAX_WPS_AP_COUNT];
1198  char tmpBuff[RETURN_BUF_LENGTH];
1199  int retry = 0;
1200  bIsWpsCompleted = FALSE;
1201  bIsPBCOverlapDetected = FALSE;
1202 
1203  // Continue scanning & try connecting Until WPS is successfull
1204  WIFI_LOG_INFO("Scanning for WPS-PBC access points on both 5 & 2.4 GHz Bands.\n");
1205  while(!bIsWpsCompleted)
1206  {
1207  pthread_mutex_lock(&wpa_sup_lock);
1208  wpaCtrlSendCmd("BSS_FLUSH 0");
1209  bNoAutoScan = TRUE;
1210  wpaCtrlSendCmd("SCAN");
1211 
1212  // Check if scanning is failed due to in progress scanning
1213  if (strstr(return_buf, "FAIL-BUSY") != NULL) {
1214  WIFI_LOG_INFO("FAIL-BUSY due to in-progress scanning.. \n");
1215  wpaCtrlSendCmd("ABORT_SCAN");
1216  wpaCtrlSendCmd("BSS_FLUSH 0");
1217  wpaCtrlSendCmd("SCAN");
1218  }
1219 
1220  pthread_mutex_unlock(&wpa_sup_lock);
1221  cur_scan_state = WIFI_HAL_WPA_SUP_SCAN_STATE_STARTED;
1222 
1223  // Lets wait for scan results for max 6 seconds
1224  retry = 0;
1225  while ((cur_scan_state != WIFI_HAL_WPA_SUP_SCAN_STATE_RESULTS_RECEIVED) &&(retry++ < 1000)) {
1226  usleep(6000);
1227  }
1228 
1229  // Get and Parse scan results and check for PBC enabled Accesspoints
1230  memset(tmpBuff,0,RETURN_BUF_LENGTH);
1231  pthread_mutex_lock(&wpa_sup_lock);
1232  wpaCtrlSendCmd("SCAN_RESULTS");
1233  log_top5_bssids(return_buf);
1234  strncpy(tmpBuff,return_buf,sizeof(tmpBuff));
1235  pthread_mutex_unlock(&wpa_sup_lock);
1236  cur_scan_state = WIFI_HAL_WPA_SUP_SCAN_STATE_IDLE;
1237  apCount = parse_wps_pbc_accesspoints(tmpBuff,ap_list);
1238  if(apCount != 0)
1239  {
1240  // Trying to get 5Ghz PBC enabled Accesspoints from scnaned list and start wps operation
1241  WIFI_LOG_INFO("Trying to establish WPS connection to 5GHz Accesspoint.\n");
1242  for(i=0; i<apCount; i++)
1243  {
1244  if(ap_list[i].ap_FreqBand == WIFI_HAL_FREQ_BAND_5GHZ)
1245  {
1246  triggerWpsPush(ap_list[i].ap_BSSID);
1247 
1248  // Initiated WPS operation let wait for results for max 5 seconds to connect
1249  retry = 0;
1250  while ((!bIsWpsCompleted) &&(retry++ < 1000)) {
1251  usleep(5000);
1252  }
1253  if(!bIsWpsCompleted)
1254  WIFI_LOG_ERROR("Failed to connect to 5G AP - %s\n",ap_list[i].ap_SSID);
1255  else {
1256  // Adding Telemetry for Successful connection
1257  WIFI_LOG_INFO("TELEMETRY_WPS_CONNECTION_STATUS:CONNECTED,%s,%s,5GHz,%d,%d \n",ap_list[i].ap_SSID,ap_list[i].ap_BSSID,ap_list[i].ap_SignalStrength,ap_list[i].ap_Frequency);
1258  return NULL;
1259  }
1260  }
1261  }
1262 
1263  // Looks like either we couldnt get a 5G AP or we couldnt connected to 5G AP. Lets try to connect to 2.4 G AP
1264  WIFI_LOG_INFO("Failed to get 5Ghz AP for WPS connection, Trying for 2.4GHz AP. \n");
1265  for(i=0; i<apCount; i++)
1266  {
1267  if(ap_list[i].ap_FreqBand == WIFI_HAL_FREQ_BAND_24GHZ)
1268  {
1269  triggerWpsPush(ap_list[i].ap_BSSID);
1270 
1271  // Initiated WPS operation let wait for results for max 5 seconds to connect
1272  retry = 0;
1273  while ((!bIsWpsCompleted) &&(retry++ < 1000)) {
1274  usleep(5000);
1275  }
1276  if(!bIsWpsCompleted) // WPS connection is failed to 2.4GHz AP,
1277  WIFI_LOG_ERROR("Failed to connect to 2.4G AP - %s\n",ap_list[i].ap_SSID);
1278  else {
1279  // Adding Telemetry for Successful Connection
1280  WIFI_LOG_INFO("TELEMETRY_WPS_CONNECTION_STATUS:CONNECTED,%s,%s,2.4GHz,%d,%d \n",ap_list[i].ap_SSID,ap_list[i].ap_BSSID,ap_list[i].ap_SignalStrength,ap_list[i].ap_Frequency);
1281  return NULL;
1282  }
1283  }
1284  }
1285  } // End Of if(apCount != 0)
1286  else
1287  {
1288  WIFI_LOG_INFO("Missing WPS_PBC AP in Scanned list, Continue Scanning... \n");
1289  }
1290  } // End of while(!bIsWpsCompleted)
1291  return NULL;
1292 }
1293 
1294 
1295 INT wifi_setCliWpsButtonPush(INT ssidIndex){
1296 
1297  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
1298 
1299  WIFI_LOG_INFO("WPS Push Button Call\n");
1300  telemetry_event_d("WIFIV_ERR_WPS_button_pressed", 1);
1301  bWpsPBC = true;
1302 
1303  pthread_mutex_lock(&wpa_sup_lock);
1304 
1305  if (cur_sup_state != WIFI_HAL_WPA_SUP_STATE_IDLE) {
1306  pthread_mutex_unlock(&wpa_sup_lock);
1307  WIFI_LOG_INFO("Connection is in progress, returning error \n");
1308  return RETURN_ERR;
1309  }
1310 
1311  isPrivateSSID=1;
1312  wpaCtrlSendCmd("REMOVE_NETWORK 0");
1313  wpaCtrlSendCmd("SAVE_CONFIG");
1314  bUpdatedSSIDInfo=1;
1315  pthread_mutex_unlock(&wpa_sup_lock);
1316 
1317  if(isDualBandSupported())
1318  {
1319  WIFI_LOG_INFO("STB is Dual-Band supported. Initiating band seletion... \n");
1320  pthread_create(&wps_start_thread, NULL, start_wifi_wps_connection, NULL);
1321  // Start WPS timer
1322  signal(SIGALRM, stop_wifi_wps_connection);
1323  alarm(WPS_CON_TIMEOUT);
1324  }
1325  else
1326  {
1327  WIFI_LOG_INFO("No Dual-Band support. Initiate Normal PBC.\n");
1328  bIsWpsCompleted = FALSE;
1329  pthread_mutex_lock(&wpa_sup_lock);
1330  wpaCtrlSendCmd("WPS_PBC");
1331  pthread_mutex_unlock(&wpa_sup_lock);
1332  }
1333 
1334  WIFI_LOG_INFO("Will be timing out if AP not found after 120 seconds\n");
1335 
1336  if (false == wpa_supplicant_conf_reset())
1337  return RETURN_ERR;
1338 
1339  wifiStatusCode_t connError;
1340  connError = WIFI_HAL_CONNECTING;
1341  (*callback_connect)(1, "", &connError);
1342  WIFI_LOG_INFO("Connection in progress..\n");
1343 
1344  WIFI_LOG_INFO("WIFI HAL: WPS Push sent successfully\n");
1345  return RETURN_OK;
1346 }
1347 
1348 INT wifi_connectEndpoint(INT ssidIndex, CHAR *AP_SSID, wifiSecurityMode_t AP_security_mode, CHAR *AP_security_WEPKey, CHAR *AP_security_PreSharedKey, CHAR *AP_security_KeyPassphrase,int saveSSID,CHAR * eapIdentity,CHAR * carootcert,CHAR * clientcert,CHAR * privatekey){
1349 
1350  int retStatus = -1;
1351  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
1352 
1353  WIFI_LOG_INFO("Save SSID value:%d\n", saveSSID);
1354 
1355  pthread_mutex_lock(&wpa_sup_lock); /* Locking in the mutex before connect */
1356  isPrivateSSID=saveSSID;
1357  if (isPrivateSSID) {
1358  WIFI_LOG_INFO("Will save network to wpa_supplicant.conf if connect is successful\n");
1359  }
1360  else { // LnF SSID
1361  WIFI_LOG_INFO("Will not save network to wpa_supplicant.conf\n");
1362  }
1363 
1364 
1365  WIFI_LOG_INFO("Requesting connection to AP\n");
1366 
1367  WIFI_LOG_INFO("Security mode:%d\n", AP_security_mode);
1368  retStatus=wpaCtrlSendCmd("REMOVE_NETWORK 0");
1369  if ((strstr (return_buf, "FAIL") != NULL) || (retStatus != 0))
1370  {
1371  WIFI_LOG_ERROR( "%s: REMOVE_NETWORK 0 failed error %d \n", __FUNCTION__,retStatus);
1372  }
1373 
1374  wpaCtrlSendCmd("ADD_NETWORK");
1375 
1376  /* Set SSID */
1377  sprintf(cmd_buf, "SET_NETWORK 0 ssid \"%s\"", AP_SSID);
1378  wpaCtrlSendCmd(cmd_buf);
1379 
1380  if (AP_security_mode == WIFI_SECURITY_WPA_PSK_AES ||
1381  AP_security_mode == WIFI_SECURITY_WPA2_PSK_AES ||
1382  AP_security_mode == WIFI_SECURITY_WPA_PSK_TKIP ||
1383  AP_security_mode == WIFI_SECURITY_WPA2_PSK_TKIP ||
1384  AP_security_mode == WIFI_SECURITY_WPA_WPA2_PSK ||
1385  AP_security_mode == WIFI_SECURITY_WPA3_PSK_AES ||
1386  AP_security_mode == WIFI_SECURITY_WPA3_SAE)
1387  {
1388  if(AP_security_mode == WIFI_SECURITY_WPA3_PSK_AES){
1389  WIFI_LOG_INFO("Security mode is WPA2/WPA3\n");
1390  }
1391  else if(AP_security_mode == WIFI_SECURITY_WPA3_SAE){
1392  WIFI_LOG_INFO("Security mode is WPA3\n");
1393  }
1394  else{
1395  WIFI_LOG_INFO("Security mode is PSK\n");
1396  }
1397  /* Key Management */
1398  sprintf(cmd_buf, "SET_NETWORK 0 key_mgmt WPA-PSK SAE");
1399  wpaCtrlSendCmd(cmd_buf);
1400 
1401 #ifdef RDKC
1402  /* Set the SAE Password */
1403  sprintf(cmd_buf, "SET_NETWORK 0 sae_password \"%s\"", AP_security_PreSharedKey);
1404  int status = wpaCtrlSendCmd(cmd_buf);
1405  if(strstr(return_buf, "FAIL") != NULL)
1406  {
1407  WIFI_LOG_ERROR("Failed to set sae_password\n");
1408  }
1409 #endif
1410 
1411  /* Set the PSK */
1412  sprintf(cmd_buf, "SET_NETWORK 0 psk \"%s\"", AP_security_PreSharedKey);
1413  wpaCtrlSendCmd(cmd_buf);
1414  if(strstr(return_buf, "FAIL") != NULL){
1415  WIFI_LOG_INFO("Password may not be falling within spec\n");
1416  wifiStatusCode_t connError;
1418  if (callback_connect)
1419  (*callback_connect)(1, AP_SSID, &connError);
1420  else {
1421  WIFI_LOG_ERROR("erorr connecting to BSS (%d), but user didn't supply callback\n",
1422  connError);
1423  }
1424  pthread_mutex_unlock(&wpa_sup_lock);
1425  if (!isPrivateSSID)
1426  {
1427  isPrivateSSID = 1;
1428  }
1429  return RETURN_OK;
1430  }
1431  }
1432  else if (AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_TKIP ||
1433  AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_AES ||
1434  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_TKIP ||
1435  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_AES ||
1436  AP_security_mode == WIFI_SECURITY_WPA_WPA2_ENTERPRISE)
1437  {
1438  WIFI_LOG_INFO("Security mode is WPA Enterprise\n");
1439  sprintf(cmd_buf, "SET_NETWORK 0 key_mgmt WPA-EAP");
1440  wpaCtrlSendCmd(cmd_buf);
1441  }
1442  else if (AP_security_mode == WIFI_SECURITY_WEP_64 ||
1443  AP_security_mode == WIFI_SECURITY_WEP_128)
1444  {
1445  wpaCtrlSendCmd("SET_NETWORK 0 key_mgmt NONE");
1446  wpaCtrlSendCmd("SET_NETWORK 0 auth_alg OPEN SHARED");
1447 
1448  /*
1449  *Set the password as string or hex depends on the WEP key format.
1450  *If password length for WEP64/WEP128 is 5/13 then it must be ASCII key format
1451  */
1452 
1453  if (strlen(AP_security_PreSharedKey) == 5 || strlen(AP_security_PreSharedKey) ==13)
1454  sprintf(cmd_buf, "SET_NETWORK 0 wep_key0 \"%s\"", AP_security_PreSharedKey);
1455  else
1456  sprintf(cmd_buf, "SET_NETWORK 0 wep_key0 %s", AP_security_PreSharedKey);
1457 
1458  wpaCtrlSendCmd(cmd_buf);
1459  }
1460  else{
1461  WIFI_LOG_INFO("None\n");
1462  sprintf(cmd_buf, "SET_NETWORK 0 key_mgmt NONE");
1463  wpaCtrlSendCmd(cmd_buf);
1464 // sprintf(cmd_buf, "SET_NETWORK 0 wep_key0 \"%s\"", AP_security_KeyPassphrase);
1465 // wpaCtrlSendCmd(cmd_buf);
1466  }
1467 
1468  /* Allow us to connect to hidden SSIDs */
1469  wpaCtrlSendCmd("SET_NETWORK 0 scan_ssid 1");
1470 
1471  if (AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_TKIP ||
1472  AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_AES ||
1473  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_TKIP ||
1474  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_AES ||
1475  AP_security_mode == WIFI_SECURITY_WPA_WPA2_ENTERPRISE ||
1476  AP_security_mode == WIFI_SECURITY_WPA_PSK_AES ||
1477  AP_security_mode == WIFI_SECURITY_WPA2_PSK_AES ||
1478  AP_security_mode == WIFI_SECURITY_WPA_WPA2_PSK)
1479  {
1480  WIFI_LOG_INFO("Setting TKIP values\n");
1481 
1482  wpaCtrlSendCmd("SET_NETWORK 0 pairwise CCMP TKIP");
1483 
1484  wpaCtrlSendCmd("SET_NETWORK 0 group CCMP TKIP");
1485 
1486  wpaCtrlSendCmd("SET_NETWORK 0 proto WPA RSN");
1487  }
1488 
1489  if (AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_TKIP ||
1490  AP_security_mode == WIFI_SECURITY_WPA_ENTERPRISE_AES ||
1491  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_TKIP ||
1492  AP_security_mode == WIFI_SECURITY_WPA2_ENTERPRISE_AES ||
1493  AP_security_mode == WIFI_SECURITY_WPA_WPA2_ENTERPRISE)
1494  {
1495  WIFI_LOG_INFO("EAP Identity %s\n", eapIdentity);
1496  sprintf(cmd_buf, "SET_NETWORK 0 identity \"%s\"", eapIdentity);
1497 
1498  wpaCtrlSendCmd(cmd_buf);
1499 
1500  wpaCtrlSendCmd("SET_NETWORK 0 eap TLS");
1501  }
1502 
1503  WIFI_LOG_INFO("The carootcert:%s\n", carootcert);
1504  WIFI_LOG_INFO("The clientcert:%s\n", clientcert);
1505  WIFI_LOG_INFO("The privatekey:%s\n", privatekey);
1506  WIFI_LOG_DEBUG("The PSK key:%s\n", AP_security_PreSharedKey);
1507  WIFI_LOG_DEBUG("The KeyP key:%s\n", AP_security_KeyPassphrase);
1508 
1509  /* EAP with certificates */
1510  if (access(carootcert, F_OK) != -1){
1511 
1512  WIFI_LOG_INFO("CA Root certificate exists\n");
1513  sprintf(cmd_buf, "SET_NETWORK 0 ca_cert \"%s\"", carootcert);
1514  wpaCtrlSendCmd(cmd_buf);
1515  }
1516 
1517  if (access(clientcert, F_OK) != -1){
1518 
1519  WIFI_LOG_INFO("Client Certificate exists\n");
1520  sprintf(cmd_buf, "SET_NETWORK 0 client_cert \"%s\"", clientcert);
1521  wpaCtrlSendCmd(cmd_buf);
1522  }
1523 
1524  if (access(privatekey, F_OK) != -1){
1525 
1526  WIFI_LOG_INFO("Private Key exists\n");
1527  sprintf(cmd_buf, "SET_NETWORK 0 private_key \"%s\"", privatekey);
1528  wpaCtrlSendCmd(cmd_buf);
1529 
1530  sprintf(cmd_buf, "SET_NETWORK 0 private_key_passwd \"%s\"", AP_security_KeyPassphrase);
1531  WIFI_LOG_INFO("Command is:%s\n", cmd_buf);
1532  wpaCtrlSendCmd(cmd_buf);
1533  }
1534 
1535  wpaCtrlSendCmd("SET_NETWORK 0 mode 0");
1536 
1537  snprintf (ssid_to_find, sizeof (ssid_to_find), "%s", AP_SSID);
1538  WIFI_LOG_INFO("Setting ssid_to_find to [%s]\n", ssid_to_find);
1539 
1540  wpaCtrlSendCmd("ENABLE_NETWORK 0");
1541  wpaCtrlSendCmd("REASSOCIATE");
1542 
1543  if(saveSSID){
1544  WIFI_LOG_INFO("Connecting to the specified access point\n");
1545  wifiStatusCode_t connError;
1546  connError = WIFI_HAL_CONNECTING;
1547  if (callback_connect) (*callback_connect)(1, AP_SSID, &connError);
1548  }
1549 
1550  WIFI_LOG_INFO("Leaving WiFi Connect Endpoint function\n");
1551  pthread_mutex_unlock(&wpa_sup_lock);
1552  return RETURN_OK;
1553 }
1554 
1556  char buf[512];
1557  char *saveptr = NULL;
1558  static char ssid[32]={0};
1559  static char bssid[20]={0};
1560  static char security[64]={0};
1561  static char passphrase[64]={0};
1562  static char wep_key[128]={0};
1563  char *tokenKey;
1564  char *tokenValue;
1565  FILE *f = NULL;
1566 
1567  if(!bUpdatedSSIDInfo)
1568  {
1569  strcpy(pairedSSIDInfo->ap_ssid, ssid);
1570  strcpy(pairedSSIDInfo->ap_bssid, bssid);
1571  strcpy(pairedSSIDInfo->ap_security, security);
1572  strcpy(pairedSSIDInfo->ap_passphrase,passphrase);
1573  strcpy(pairedSSIDInfo->ap_wep_key,wep_key);
1574  return RETURN_OK;
1575  }
1576  f = fopen("/opt/secure/wifi/wpa_supplicant.conf", "r");
1577  if (NULL == f)
1578  {
1579  WIFI_LOG_ERROR("Failed to open wpa_supplicant.conf\n");
1580  return RETURN_ERR;
1581  }
1582  while (fgets(buf, sizeof(buf), f) != NULL)
1583  {
1584  tokenKey=strtok_r(buf,"\"=", &saveptr);
1585  if (tokenKey == NULL)
1586  continue;
1587  tokenValue=strtok_r(NULL,"\"=\n", &saveptr);
1588  trimSpace(tokenKey);
1589  if((tokenValue != NULL) && (strcasecmp(tokenKey,"ssid") == 0))
1590  {
1591  strcpy(pairedSSIDInfo->ap_ssid,tokenValue);
1592  strcpy(ssid,tokenValue);
1593  bUpdatedSSIDInfo=0;
1594  }
1595  else if((tokenValue != NULL) && (strcasecmp(tokenKey,"psk") == 0))
1596  {
1597  strcpy(pairedSSIDInfo->ap_passphrase,tokenValue);
1598  strcpy(passphrase,tokenValue);
1599  }
1600  else if((tokenValue != NULL) && (strcasecmp(tokenKey,"bssid") == 0))
1601  {
1602  strcpy(pairedSSIDInfo->ap_bssid,tokenValue);
1603  strcpy(bssid,tokenValue);
1604  }
1605  else if((tokenValue != NULL) && (strcasecmp(tokenKey,"key_mgmt") == 0))
1606  {
1607  trimSpace(tokenValue);
1608  strcpy(pairedSSIDInfo->ap_security,tokenValue);
1609  strcpy(security,tokenValue);
1610  }
1611  else if((tokenValue != NULL) && (strstr(tokenKey,"wep_key") != 0))
1612  {
1613  trimSpace(tokenValue);
1614  strcpy(pairedSSIDInfo->ap_wep_key,tokenValue);
1615  strcpy(wep_key,tokenValue);
1616  strcpy(pairedSSIDInfo->ap_passphrase,tokenValue);//Incase of WEP, wep_key is printed for passphrase
1617  strcpy(passphrase,tokenValue);
1618  }
1619  }
1620  fclose(f);
1621 
1622  if(pairedSSIDInfo->ap_ssid[0] == '\0') {
1623  WIFI_LOG_ERROR("No SSID in wpa_supplicant.conf\n");
1624  telemetry_event_d("WIFIV_ERR_NoSSIDconf", 1);
1625  return RETURN_ERR;
1626  }
1627 
1628  WIFI_LOG_DEBUG("%s: ap_ssid=[%s], ap_bssid=[%s]\n",
1629  __FUNCTION__, pairedSSIDInfo->ap_ssid, pairedSSIDInfo->ap_bssid);
1630 
1631  // BSSID will be empty if wpa_supplicant.conf does not have it
1632  // in this case, get BSSID from output of wpa control interface command "STATUS"
1633  // but use BSSID from "STATUS" only if SSID from "STATUS" = SSID from conf file (as any SSID not in conf file should be ignored)
1634  if (pairedSSIDInfo->ap_ssid[0] != '\0' && pairedSSIDInfo->ap_bssid[0] == '\0') // wpa_supplicant.conf file has SSID but not BSSID
1635  {
1636  pthread_mutex_lock(&wpa_sup_lock);
1637  int retStatus = wpaCtrlSendCmd("STATUS");
1638  if (retStatus == -2)
1639  telemetry_event_d("WIFIV_WARN_hal_timeout", 1);
1640  const char* current_bssid = getValue(return_buf, "bssid");
1641  WIFI_LOG_DEBUG("%s: current_bssid=[%s]\n", __FUNCTION__, current_bssid);
1642  if (current_bssid)
1643  {
1644  const char *ssid_ptr = getValue((char*) (strchr(current_bssid, '\0') + 1), "ssid"); // look for ssid after end of bssid
1645  WIFI_LOG_DEBUG("%s: ssid_ptr=[%s]\n", __FUNCTION__, ssid_ptr);
1646  if (ssid_ptr)
1647  {
1648  char current_ssid[MAX_SSID_LEN+1] = {0};
1649  printf_decode ((u8*)current_ssid, sizeof(current_ssid), ssid_ptr);
1650  WIFI_LOG_DEBUG("%s: current_ssid=[%s]\n", __FUNCTION__, current_ssid);
1651  if (strcmp(pairedSSIDInfo->ap_ssid, current_ssid) == 0)
1652  {
1653  snprintf (pairedSSIDInfo->ap_bssid, sizeof(pairedSSIDInfo->ap_bssid), "%s", current_bssid);
1654  snprintf (bssid, sizeof(bssid), "%s", current_bssid);
1655  WIFI_LOG_DEBUG("%s: current_ssid matches ap_ssid. ap_bssid set to [%s]\n",
1656  __FUNCTION__, pairedSSIDInfo->ap_bssid);
1657  }
1658  }
1659  }
1660  pthread_mutex_unlock(&wpa_sup_lock);
1661  }
1662 
1663  return RETURN_OK;
1664 }
1665 
1666 INT wifi_disconnectEndpoint(INT ssidIndex, CHAR *AP_SSID){
1667 
1668  WIFI_LOG_INFO("SSID Index is not applicable here since this is a STA.. Printing SSID Index:%d\n", ssidIndex);
1669 
1670  WIFI_LOG_INFO("Received request to disconnect from AP\n");
1671 
1672  wpaCtrlSendCmd("DISCONNECT");
1673 
1674  return RETURN_OK;
1675 }
1676 
1677 // Clear SSID info from HAL
1678 INT wifi_clearSSIDInfo(INT ssidIndex) {
1679 
1680  int status = RETURN_ERR;
1681 
1682  pthread_mutex_lock(&wpa_sup_lock);
1683  if (wpaCtrlSendCmd("REMOVE_NETWORK 0") == RETURN_OK) {
1684  if(wpaCtrlSendCmd("SAVE_CONFIG") == RETURN_OK) {
1685  WIFI_LOG_INFO("Cleared ssid info successfully. \n");
1686  status = RETURN_OK;
1687  } else {
1688  WIFI_LOG_ERROR("Error in saving configuration. \n ");
1689  }
1690  } else {
1691  WIFI_LOG_ERROR("Error in removing network. \n");
1692  }
1693  pthread_mutex_unlock(&wpa_sup_lock);
1694  return status;
1695 }
1696 
1697 
1698 #ifdef WIFI_CLIENT_ROAMING
1699 
1700 static int wifi_set_signal_monitor(int rssi_threshold)
1701 {
1702  int status = RETURN_ERR;
1703  char cmd[BUFF_LEN_64];
1704 
1705  memset(cmd,0,sizeof(cmd));
1706  sprintf(cmd,"SIGNAL_MONITOR THRESHOLD=%d HYSTERESIS=2",rssi_threshold); // Adding HYSTERESIS to reduce events overhead.
1707  pthread_mutex_lock(&wpa_sup_lock);
1708  wpaCtrlSendCmd("SIGNAL_MONITOR");
1709  status = wpaCtrlSendCmd(cmd);
1710  pthread_mutex_unlock(&wpa_sup_lock);
1711  if(status == RETURN_OK) {
1712  WIFI_LOG_INFO("Successfully started RSSI Signal monitor.\n ");
1713  } else {
1714  WIFI_LOG_ERROR("Failed to start RSSI Signal monitor. !\n ");
1715  }
1716  return status;
1717 }
1718 
1719 static int wifi_is_valid_threshold(int threshold)
1720 {
1721  return ((threshold <= 0) && (threshold >= -200));
1722 }
1723 
1724 int wifi_setRoamingControl (int ssidIndex, wifi_roamingCtrl_t *pRoamingCtrlCfg)
1725 {
1726  wifi_roamingCtrl_t currentCfg;
1727  int status = -1;
1728  char cmd[64];
1729  int refreshNeeded = 0;
1730 
1731  if(NULL == pRoamingCtrlCfg) {
1732  WIFI_LOG_ERROR("Input pointer is NULL \n");
1733  return -1;
1734  }
1735  memset(&currentCfg,0,sizeof(currentCfg));
1736 
1737  // Get Curret Configurations and set individual param only if changed
1738  status = wifi_getRoamingControl(ssidIndex,&currentCfg);
1739  if(status == 0) {
1740  if(currentCfg.roamingEnable != pRoamingCtrlCfg->roamingEnable) {
1741  snprintf(cmd_buf, sizeof(cmd_buf), "SET roaming_enable %d", pRoamingCtrlCfg->roamingEnable);
1742  pthread_mutex_lock(&wpa_sup_lock);
1743  status = wpaCtrlSendCmd(cmd_buf);
1744  pthread_mutex_unlock(&wpa_sup_lock);
1745  refreshNeeded = true;
1746  if(status != 0) {
1747  WIFI_LOG_ERROR("Failed to set roaming enable.! \n");
1748  return RETURN_ERR;
1749  }
1750  WIFI_LOG_INFO("Successfully set roamingEnable to %d\n", pRoamingCtrlCfg->roamingEnable);
1751  } else {
1752  WIFI_LOG_DEBUG("Trying to set same value for roamingEnable, Ignoring SET operation.\n");
1753  }
1754  pstRoamingCtrl.roamingEnable = pRoamingCtrlCfg->roamingEnable;
1755 
1756  // Check Roaming is enabled Or Not, If Not DONOT Allow to SET/GET
1757  /* if(pRoamingCtrlCfg->roamingEnable == 0 && currentCfg.roamingEnable == 0) {
1758  WIFI_LOG_ERROR("Romaing Feature is not enabled, Ignoring SET request.!\n");
1759  return -2;
1760  } */
1761 
1762  if(currentCfg.preassnBestThreshold != pRoamingCtrlCfg->preassnBestThreshold && wifi_is_valid_threshold(pRoamingCtrlCfg->preassnBestThreshold)) {
1763  snprintf(cmd_buf, sizeof(cmd_buf), "SET pre_assn_best_threshold_level %d", pRoamingCtrlCfg->preassnBestThreshold);
1764  pthread_mutex_lock(&wpa_sup_lock);
1765  status = wpaCtrlSendCmd(cmd_buf);
1766  pthread_mutex_unlock(&wpa_sup_lock);
1767  if(status != 0) {
1768  WIFI_LOG_ERROR("Failed to set pre_assn_best_threshold_level.! \n");
1769  return RETURN_ERR;
1770  }
1771  WIFI_LOG_INFO("Successfully set preassnBestThreshold to %d\n", pRoamingCtrlCfg->preassnBestThreshold);
1772  } else if(currentCfg.preassnBestThreshold == pRoamingCtrlCfg->preassnBestThreshold)
1773  WIFI_LOG_DEBUG("Trying to set same value for preassnBestThreshold, Ignoring SET operation.\n");
1774  else{
1775  WIFI_LOG_ERROR("Failed to set pre_assn_best_threshold_level - Invalid value = %d \n",pRoamingCtrlCfg->preassnBestThreshold);
1776  return RETURN_ERR;
1777  }
1778  pstRoamingCtrl.preassnBestThreshold = pRoamingCtrlCfg->preassnBestThreshold;
1779 
1780  if(currentCfg.preassnBestDelta != pRoamingCtrlCfg->preassnBestDelta) {
1781  snprintf(cmd_buf, sizeof(cmd_buf), "SET pre_assn_best_delta_level %d", pRoamingCtrlCfg->preassnBestDelta);
1782  pthread_mutex_lock(&wpa_sup_lock);
1783  status = wpaCtrlSendCmd(cmd_buf);
1784  pthread_mutex_unlock(&wpa_sup_lock);
1785  if(status != 0) {
1786  WIFI_LOG_ERROR("Failed to set pre_assn_best_delta_level.! \n");
1787  return RETURN_ERR;
1788  }
1789  WIFI_LOG_INFO("Successfully set preassnBestDelta to %d\n", pRoamingCtrlCfg->preassnBestDelta);
1790  } else {
1791  WIFI_LOG_DEBUG("Trying to set same value for preassnBestDelta, Ignoring SET operation.\n");
1792  }
1793  pstRoamingCtrl.preassnBestDelta = pRoamingCtrlCfg->preassnBestDelta;
1794 
1795  // Setting Post Association params
1796  if(currentCfg.roam80211kvrEnable != pRoamingCtrlCfg->roam80211kvrEnable) {
1797  snprintf(cmd_buf, sizeof(cmd_buf), "SET kvr_enable %d", pRoamingCtrlCfg->roam80211kvrEnable);
1798  pthread_mutex_lock(&wpa_sup_lock);
1799  wpaCtrlSendCmd(cmd_buf);
1800  pthread_mutex_unlock(&wpa_sup_lock);
1801  WIFI_LOG_INFO("Successfully set 80211kvrEnable to %d\n", pRoamingCtrlCfg->roam80211kvrEnable);
1802  } else {
1803  WIFI_LOG_DEBUG("Trying to set same value for 80211kvrEnable,Ignoring SET operation.\n");
1804  }
1805  pstRoamingCtrl.roam80211kvrEnable = pRoamingCtrlCfg->roam80211kvrEnable;
1806 
1807  // Save the current values to persistent file
1808  pthread_mutex_lock(&wpa_sup_lock);
1809  wpaCtrlSendCmd("SAVE_CONFIG");
1810  pthread_mutex_unlock(&wpa_sup_lock);
1811 
1812  } else {
1813  WIFI_LOG_ERROR("Failed to get current roaming Config \n");
1814  }
1815  // Setting Post Association params
1816 
1817  if(pstRoamingCtrl.selfSteerOverride != pRoamingCtrlCfg->selfSteerOverride) {
1818  pstRoamingCtrl.selfSteerOverride = pRoamingCtrlCfg->selfSteerOverride;
1819  refreshNeeded = true;
1820  WIFI_LOG_INFO("Successfully set selfSteerOverride to %d\n", pstRoamingCtrl.selfSteerOverride);
1821  } else {
1822  WIFI_LOG_DEBUG("Trying to set same value for selfSteerOverride, Ignoring SET operation.\n");
1823  }
1824  // Set Roaming Mode
1825  if((pstRoamingCtrl.roam80211kvrEnable == true) && (pstRoamingCtrl.selfSteerOverride == false)) {
1826  cur_roaming_mode = WIFI_HAL_ROAMING_MODE_AP_STEERING;
1827  WIFI_LOG_INFO("Setting Roaming mode to AP Controlled..\n");
1828  }
1829  else {
1830  cur_roaming_mode = WIFI_HAL_ROAMING_MODE_SELF_STEERING;
1831  WIFI_LOG_INFO("Setting Roaming mode to Self Steering..\n");
1832  }
1833 
1834  if(pstRoamingCtrl.postAssnLevelDeltaConnected != pRoamingCtrlCfg->postAssnLevelDeltaConnected) {
1835  pstRoamingCtrl.postAssnLevelDeltaConnected = pRoamingCtrlCfg->postAssnLevelDeltaConnected;
1836  WIFI_LOG_INFO("Successfully set postAssnLevelDeltaConnected to %d\n", pstRoamingCtrl.postAssnLevelDeltaConnected);
1837  } else {
1838  WIFI_LOG_DEBUG("Trying to set same value for postAssnLevelDeltaConnected,Ignoring SET operation.\n");
1839  }
1840 
1841  if(pstRoamingCtrl.postAssnLevelDeltaDisconnected != pRoamingCtrlCfg->postAssnLevelDeltaDisconnected) {
1842  pstRoamingCtrl.postAssnLevelDeltaDisconnected = pRoamingCtrlCfg->postAssnLevelDeltaDisconnected;
1843  WIFI_LOG_INFO("Successfully set postAssnLevelDeltaDisconnected to %d\n", pstRoamingCtrl.postAssnLevelDeltaDisconnected);
1844  } else {
1845  WIFI_LOG_DEBUG("Trying to set same value for postAssnLevelDeltaDisconnected,Ignoring SET operation.\n");
1846  }
1847 
1848  if(pstRoamingCtrl.postAssnSelfSteerThreshold != pRoamingCtrlCfg->postAssnSelfSteerThreshold && wifi_is_valid_threshold(pRoamingCtrlCfg->postAssnSelfSteerThreshold)) {
1849  pstRoamingCtrl.postAssnSelfSteerThreshold = pRoamingCtrlCfg->postAssnSelfSteerThreshold;
1850  refreshNeeded = true;
1851  WIFI_LOG_INFO("Successfully set postAssnSelfSteerThreshold to %d\n",pstRoamingCtrl.postAssnSelfSteerThreshold);
1852  } else if(pstRoamingCtrl.postAssnSelfSteerThreshold == pRoamingCtrlCfg->postAssnSelfSteerThreshold) {
1853  WIFI_LOG_DEBUG("Trying to set same value for postAssnSelfSteerThreshold,Ignoring SET operation.\n");
1854  } else {
1855  WIFI_LOG_ERROR("Failed to set postAssnSelfSteerThreshold, Invalid Value = %d.\n",pRoamingCtrlCfg->postAssnSelfSteerThreshold);
1856  }
1857 
1858  if(pstRoamingCtrl.postAssnSelfSteerTimeframe != pRoamingCtrlCfg->postAssnSelfSteerTimeframe && pRoamingCtrlCfg->postAssnSelfSteerTimeframe >= 0) {
1859  pstRoamingCtrl.postAssnSelfSteerTimeframe = pRoamingCtrlCfg->postAssnSelfSteerTimeframe;
1860  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Timer changed, Refresh backoff
1861  backOffRefreshed = 1;
1862  WIFI_LOG_INFO("Successfully set postAssnSelfSteerTimeframe to %d\n", pstRoamingCtrl.postAssnSelfSteerTimeframe);
1863  } else if(pRoamingCtrlCfg->postAssnSelfSteerTimeframe < 0 ) {
1864  WIFI_LOG_ERROR("Failed to set postAssnSelfSteerTimeframe, Invalid Value = %d.\n",pRoamingCtrlCfg->postAssnSelfSteerTimeframe);
1865  }
1866 
1867  if(pstRoamingCtrl.postAssnBackOffTime != pRoamingCtrlCfg->postAssnBackOffTime) {
1868  pstRoamingCtrl.postAssnBackOffTime = pRoamingCtrlCfg->postAssnBackOffTime;
1869  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime;
1870  backOffRefreshed = 1;
1871  WIFI_LOG_INFO("Successfully set postAssnBackOffTime to %d\n", pstRoamingCtrl.postAssnBackOffTime);
1872  } else {
1873  WIFI_LOG_DEBUG("Trying to set same value for postAssnBackOffTime,Ignoring SET operation.\n");
1874  }
1875 
1876  if(pstRoamingCtrl.postAssnAPctrlThreshold != pRoamingCtrlCfg->postAssnAPctrlThreshold && wifi_is_valid_threshold(pRoamingCtrlCfg->postAssnAPctrlThreshold)) {
1877  pstRoamingCtrl.postAssnAPctrlThreshold = pRoamingCtrlCfg->postAssnAPctrlThreshold;
1878  refreshNeeded = true;
1879  WIFI_LOG_INFO("Successfully set postAssnAPctrlThreshold to %d\n", pstRoamingCtrl.postAssnAPctrlThreshold);
1880  } else if(pstRoamingCtrl.postAssnAPctrlThreshold == pRoamingCtrlCfg->postAssnAPctrlThreshold) {
1881  WIFI_LOG_DEBUG("Trying to set same value for postAssnAPctrlThreshold,Ignoring SET operation.\n");
1882  } else {
1883  WIFI_LOG_ERROR("Failed to set postAssnAPctrlThreshold, Invalid Value = %d.\n",pRoamingCtrlCfg->postAssnAPctrlThreshold);
1884  }
1885 
1886  if(pstRoamingCtrl.postAssnAPctrlTimeframe != pRoamingCtrlCfg->postAssnAPctrlTimeframe && pRoamingCtrlCfg->postAssnAPctrlTimeframe >= 0) {
1887  pstRoamingCtrl.postAssnAPctrlTimeframe = pRoamingCtrlCfg->postAssnAPctrlTimeframe;
1888  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Timer changed, Refresh backoff
1889  backOffRefreshed = 1;
1890  WIFI_LOG_INFO("Successfully set postAssnAPctrlTimeframe to %d\n", pstRoamingCtrl.postAssnAPctrlTimeframe);
1891  } else if(pstRoamingCtrl.postAssnAPctrlTimeframe == pRoamingCtrlCfg->postAssnAPctrlTimeframe){
1892  WIFI_LOG_DEBUG("Trying to set same value for postAssnAPctrlTimeframe,Ignoring SET operation.\n");
1893  } else {
1894  WIFI_LOG_ERROR("Failed to set postAssnAPctrlTimeframe, Invalid Value = %d.\n",pRoamingCtrlCfg->postAssnAPctrlTimeframe);
1895  }
1896 
1897  // Refresh Signal monitor if threshold or roaming mode is changed
1898  if((pstRoamingCtrl.roamingEnable == true) && (refreshNeeded == true)) {
1899  if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_SELF_STEERING ) {
1900  // Enable signal monitor if Roaming is enabled, Also reset BackOff
1901  wifi_set_signal_monitor(pstRoamingCtrl.postAssnSelfSteerThreshold);
1902  } else if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_AP_STEERING) {
1903  wifi_set_signal_monitor(pstRoamingCtrl.postAssnAPctrlThreshold);
1904  }
1905  } else if((pstRoamingCtrl.roamingEnable == false) && (refreshNeeded == true)) {
1906  // Disable Signal Monitor
1907  pthread_mutex_lock(&wpa_sup_lock);
1908  wpaCtrlSendCmd("SIGNAL_MONITOR");
1909  pthread_mutex_unlock(&wpa_sup_lock);
1910  // Disable if any in progress Roaming
1911  if( cur_roaming_state == WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_STARTED) {
1912  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Roaming Disabled, Refresh backoff
1913  backOffRefreshed = 1;
1914  pthread_cond_signal(&cond);
1915  }
1916  }
1917 
1918  // Save to persistent storage
1919  status = persist_roaming_config(&pstRoamingCtrl);
1920  if(status != RETURN_OK)
1921  WIFI_LOG_ERROR("Failed to save roaming Configuration.! \n");
1922  return status;
1923 }
1924 
1925 int persist_roaming_config(wifi_roamingCtrl_t* pRoamingCtrl_data)
1926 {
1927  cJSON *pRoamingCtrl_Json_Data = NULL;
1928  int retValue = 0;
1929 
1930  if (pRoamingCtrl_data != NULL) {
1931  pRoamingCtrl_Json_Data = cJSON_CreateObject();
1932  if(!pRoamingCtrl_Json_Data) {
1933  WIFI_LOG_ERROR("Failed to create JSON object \n");
1934  return RETURN_ERR;
1935  }
1936 
1937  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "roamingEnable", pRoamingCtrl_data->roamingEnable);
1938  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "preassnBestThreshold", pRoamingCtrl_data->preassnBestThreshold);
1939  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "preassnBestDelta", pRoamingCtrl_data->preassnBestDelta);
1940 
1941  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "selfSteerOverride", pRoamingCtrl_data->selfSteerOverride);
1942  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnLevelDeltaConnected", pRoamingCtrl_data->postAssnLevelDeltaConnected);
1943  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnLevelDeltaDisconnected", pRoamingCtrl_data->postAssnLevelDeltaDisconnected);
1944  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnSelfSteerThreshold", pRoamingCtrl_data->postAssnSelfSteerThreshold);
1945  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnSelfSteerTimeframe", pRoamingCtrl_data->postAssnSelfSteerTimeframe);
1946  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnBackOffTime", pRoamingCtrl_data->postAssnBackOffTime);
1947 
1948  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnAPctrlThreshold", pRoamingCtrl_data->postAssnAPctrlThreshold);
1949  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "postAssnAPctrlTimeframe", pRoamingCtrl_data->postAssnAPctrlTimeframe);
1950  cJSON_AddNumberToObject(pRoamingCtrl_Json_Data, "80211kvrEnable", pRoamingCtrl_data->roam80211kvrEnable);
1951 
1952  if( writeToPersistentFile(WIFI_ROAMING_CONFIG_FILE , pRoamingCtrl_Json_Data) != 0)
1953  retValue = -1;
1954  cJSON_Delete(pRoamingCtrl_Json_Data);
1955  } else {
1956  retValue = -1;
1957  WIFI_LOG_ERROR("Input config is NULL, failed to save roaming config \n");
1958  }
1959  return retValue;
1960 }
1961 int wifi_getRoamingControl(INT ssidIndex, wifi_roamingCtrl_t *pRoamingCtrlCfg)
1962 {
1963  char* ptr = NULL;
1964  int retStatus = RETURN_OK;
1965 
1966  WIFI_LOG_DEBUG("Entering ... (%s) \n",__FUNCTION__);
1967 
1968  if(pRoamingCtrlCfg == NULL) {
1969  WIFI_LOG_ERROR("Input Stats is NULL \n");
1970  return RETURN_ERR;
1971  }
1972  memcpy(pRoamingCtrlCfg,&pstRoamingCtrl,sizeof(wifi_roamingCtrl_t));
1973  // TODO :- Optimize Get Operation, Returning Global is Sufficient . ?
1974  pthread_mutex_lock(&wpa_sup_lock);
1975  retStatus = wpaCtrlSendCmd("GET roaming_controls");
1976  if(retStatus == 0)
1977  {
1978  ptr = getValue(return_buf, "roaming_enable");
1979  if (ptr == NULL) {
1980  WIFI_LOG_ERROR("Failure in getting roaming_enable. \n");
1981  retStatus = RETURN_ERR;
1982  goto exit_err;
1983  }
1984  else {
1985  pRoamingCtrlCfg->roamingEnable = strtol(ptr,NULL,10);
1986  WIFI_LOG_DEBUG("[%s] Roaming Enable = %d\n",__FUNCTION__,pRoamingCtrlCfg->roamingEnable);
1987  }
1988  ptr = ptr + strlen(ptr) + 1;
1989  ptr = getValue(ptr, "pre_assn_best_threshold_level");
1990  if (ptr == NULL) {
1991  WIFI_LOG_ERROR("Failure in getting pre_assn_best_threshold_level. \n");
1992  retStatus = RETURN_ERR;
1993  goto exit_err;
1994  }
1995  else {
1996  pRoamingCtrlCfg->preassnBestThreshold = strtol(ptr,NULL,10);
1997  WIFI_LOG_DEBUG("[%s] preassnBestThreshold = %d\n",__FUNCTION__,pRoamingCtrlCfg->preassnBestThreshold);
1998  }
1999  ptr = ptr + strlen(ptr) + 1;
2000  ptr = getValue(ptr, "pre_assn_best_delta_level");
2001  if (ptr == NULL) {
2002  WIFI_LOG_ERROR("Failure in getting pre_assn_best_delta_level. \n");
2003  retStatus = RETURN_ERR;
2004  goto exit_err;
2005  }
2006  else {
2007  pRoamingCtrlCfg->preassnBestDelta = strtol(ptr,NULL,10);
2008  WIFI_LOG_DEBUG("[%s] preassnBestDelta = %d\n",__FUNCTION__,pRoamingCtrlCfg->preassnBestDelta);
2009  }
2010  ptr = ptr + strlen(ptr) + 1;
2011  ptr = getValue(ptr, "kvr_enable");
2012  if (ptr == NULL) {
2013  // kvr_enable is not a mandatory param, in xi5 this param will not be available , hence don't return failure.
2014  WIFI_LOG_ERROR("Failure in getting kvr_enable. \n");
2015  } else {
2016  pRoamingCtrlCfg->roam80211kvrEnable = strtol(ptr,NULL,10);
2017  WIFI_LOG_DEBUG("[%s] roam80211kvrEnable = %d\n",__FUNCTION__,pRoamingCtrlCfg->roam80211kvrEnable);
2018  }
2019 
2020  } else {
2021  WIFI_LOG_ERROR("GET ROAMING_CONTROLS failed , Status = %d \n",retStatus);
2022  retStatus = RETURN_ERR;
2023  }
2024 exit_err:
2025  pthread_mutex_unlock(&wpa_sup_lock);
2026  return retStatus;
2027 }
2028 
2029 char* readPersistentFile(char *fileName)
2030 {
2031  FILE *fp = NULL;
2032  char *fileContent = NULL;
2033  if( 0 == access(fileName, F_OK) )
2034  {
2035  fp = fopen(fileName, "r");
2036  if (fp == NULL)
2037  {
2038  WIFI_LOG_ERROR("Failed to open persistent file. !\n ");
2039  }
2040  else
2041  {
2042  int ch_count = 0;
2043  fseek(fp, 0, SEEK_END);
2044  ch_count = ftell(fp);
2045  fseek(fp, 0, SEEK_SET);
2046  fileContent = (char *) malloc(sizeof(char) * (ch_count + 1));
2047  if(fileContent == NULL) {
2048  WIFI_LOG_ERROR("Failed to allocate memory, readPersistentFile failed.\n ");
2049  fclose(fp);
2050  return fileContent;
2051  }
2052  fread(fileContent, 1, ch_count,fp);
2053  fileContent[ch_count] ='\0';
2054  fclose(fp);
2055  }
2056  }
2057  else
2058  {
2059  WIFI_LOG_ERROR("Missing persistent file!\n ");
2060  }
2061  return fileContent;
2062 }
2063 int writeToPersistentFile (char* fileName, cJSON* pRoaming_Data)
2064 {
2065  FILE *fp = NULL;
2066  fp = fopen(fileName, "w");
2067  if (fp == NULL)
2068  {
2069  WIFI_LOG_ERROR("Failed to open persistent file. !\n ");
2070  return -1;
2071  }
2072  else
2073  {
2074  char* fileContent = cJSON_Print(pRoaming_Data);
2075  if(fileContent != NULL) {
2076  fprintf(fp, "%s", fileContent);
2077  free(fileContent);
2078  WIFI_LOG_DEBUG("Persistent file saved successfully.\n ");
2079  } else {
2080  WIFI_LOG_ERROR("Failed to format Json to string. !\n ");
2081  }
2082  fclose(fp);
2083  }
2084  return 0;
2085 }
2086 int initialize_roaming_config()
2087 {
2088  char *pRoamingCtrl_data_file_content = NULL;
2089  int retValue = 0;
2090  int ssidIndex = 0;
2091  wifi_roamingCtrl_t pRoamingCtrl_data;
2092  cJSON *pRoamingCtrl_json = NULL;
2093 
2094  memset(&pRoamingCtrl_data,0,sizeof(wifi_roamingCtrl_t));
2095  memset(&pstRoamingCtrl,0,sizeof(wifi_roamingCtrl_t));
2096 
2097  // Initialize default values
2098  pRoamingCtrl_data.roamingEnable = WIFI_DEFAULT_ROAMING_ENABLE;
2099  pRoamingCtrl_data.preassnBestThreshold = WIFI_DEFAULT_PRE_ASSN_BEST_THRLD;
2100  pRoamingCtrl_data.preassnBestDelta = WIFI_DEFAULT_PRE_ASSN_BEST_DELTA;
2101  pRoamingCtrl_data.selfSteerOverride = WIFI_DEFAULT_SELF_STEER_OVERRIDE_ENABLE;
2102  pRoamingCtrl_data.postAssnLevelDeltaConnected = WIFI_DEFAULT_BEST_DELTA_CONNECTED;
2103  pRoamingCtrl_data.postAssnSelfSteerThreshold = WIFI_DEFAULT_POST_ASSN_SELF_STEER_THRESHOLD;
2104  pRoamingCtrl_data.postAssnSelfSteerTimeframe = WIFI_DEFAULT_POST_ASSN_SELF_STEER_TIMEFRAME;
2105  pRoamingCtrl_data.postAssnBackOffTime = WIFI_DEFAULT_POST_ASSN_BACKOFF_TIME;
2106  pRoamingCtrl_data.postAssnLevelDeltaDisconnected = WIFI_DEFAULT_BEST_DELTA_DISCONNECTED;
2107  pRoamingCtrl_data.postAssnAPctrlThreshold = WIFI_DEFAULT_AP_CONTROL_THRESHOLD;
2108  pRoamingCtrl_data.postAssnAPctrlTimeframe = WIFI_DEFAULT_AP_CONTROL_TIMEFRAME;
2109  pRoamingCtrl_data.roam80211kvrEnable = false;
2110 
2111  pRoamingCtrl_data_file_content = readPersistentFile(WIFI_ROAMING_CONFIG_FILE);
2112  // check if file is empty
2113  if(NULL == pRoamingCtrl_data_file_content) {
2114  WIFI_LOG_ERROR("Failed to read persistent file. !\n ");
2115  }
2116  if(pRoamingCtrl_data_file_content) {
2117  pRoamingCtrl_json = cJSON_Parse(pRoamingCtrl_data_file_content);
2118  free(pRoamingCtrl_data_file_content);
2119  }
2120 
2121  if(NULL == pRoamingCtrl_json) {
2122  WIFI_LOG_ERROR("Failed to parse configuration file !\n ");
2123  }
2124  else {
2125 
2126  if( !(cJSON_GetObjectItem(pRoamingCtrl_json,"roamingEnable")) || !(cJSON_GetObjectItem(pRoamingCtrl_json,"preassnBestThreshold") || !(cJSON_GetObjectItem(pRoamingCtrl_json,"preassnBestDelta")))) {
2127  WIFI_LOG_ERROR("Corrupted roaming values, Unable to load intial configs !\n ");
2128  } else {
2129  pRoamingCtrl_data.roamingEnable = cJSON_GetObjectItem(pRoamingCtrl_json,"roamingEnable")->valueint;
2130  pRoamingCtrl_data.preassnBestThreshold = cJSON_GetObjectItem(pRoamingCtrl_json,"preassnBestThreshold")->valueint;
2131  pRoamingCtrl_data.preassnBestDelta = cJSON_GetObjectItem(pRoamingCtrl_json,"preassnBestDelta")->valueint;
2132  }
2133  if(cJSON_GetObjectItem(pRoamingCtrl_json,"selfSteerOverride")) {
2134  pRoamingCtrl_data.selfSteerOverride = cJSON_GetObjectItem(pRoamingCtrl_json,"selfSteerOverride")->valueint;
2135  }
2136  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnLevelDeltaConnected")) {
2137  pRoamingCtrl_data.postAssnLevelDeltaConnected = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnLevelDeltaConnected")->valueint;
2138  }
2139  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnSelfSteerThreshold")) {
2140  pRoamingCtrl_data.postAssnSelfSteerThreshold = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnSelfSteerThreshold")->valueint;
2141  }
2142  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnSelfSteerTimeframe")) {
2143  pRoamingCtrl_data.postAssnSelfSteerTimeframe = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnSelfSteerTimeframe")->valueint;
2144  }
2145  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnBackOffTime")) {
2146  pRoamingCtrl_data.postAssnBackOffTime = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnBackOffTime")->valueint;
2147  }
2148  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnLevelDeltaDisconnected")) {
2149  pRoamingCtrl_data.postAssnLevelDeltaDisconnected = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnLevelDeltaDisconnected")->valueint;
2150  }
2151  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnAPctrlThreshold")) {
2152  pRoamingCtrl_data.postAssnAPctrlThreshold = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnAPctrlThreshold")->valueint;
2153  }
2154  if(cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnAPctrlTimeframe")) {
2155  pRoamingCtrl_data.postAssnAPctrlTimeframe = cJSON_GetObjectItem(pRoamingCtrl_json,"postAssnAPctrlTimeframe")->valueint;
2156  }
2157  if(cJSON_GetObjectItem(pRoamingCtrl_json,"80211kvrEnable")) {
2158  pRoamingCtrl_data.roam80211kvrEnable = cJSON_GetObjectItem(pRoamingCtrl_json,"80211kvrEnable")->valueint;
2159  }
2160  cJSON_Delete(pRoamingCtrl_json);
2161  }
2162 
2163  // Setting Initial Values
2164  WIFI_LOG_INFO("Setting Initial Roaming Configuration :- [roamingEnable=%d,preassnBestThreshold=%d,preassnBestDelta=%d,selfSteerOverride=%d,postAssnLevelDeltaConnected=%d,postAssnSelfSteerThreshold=%d,postAssnSelfSteerTimeframe=%d,postAssnBackOffTime=%d,postAssnLevelDeltaDisconnected=%d,postAssnAPcontrolThresholdLevel=%d,postAssnAPcontrolTimeframe=%d,80211kvrEnable=%d]\n",pRoamingCtrl_data.roamingEnable,pRoamingCtrl_data.preassnBestThreshold,pRoamingCtrl_data.preassnBestDelta,pRoamingCtrl_data.selfSteerOverride,pRoamingCtrl_data.postAssnLevelDeltaConnected,pRoamingCtrl_data.postAssnSelfSteerThreshold,pRoamingCtrl_data.postAssnSelfSteerTimeframe,pRoamingCtrl_data.postAssnBackOffTime,pRoamingCtrl_data.postAssnLevelDeltaDisconnected,pRoamingCtrl_data.postAssnAPctrlThreshold,pRoamingCtrl_data.postAssnAPctrlTimeframe,pRoamingCtrl_data.roam80211kvrEnable);
2165 
2166  wifi_setRoamingControl(ssidIndex,&pRoamingCtrl_data);
2167  return RETURN_OK;
2168 }
2169 #endif
2170 int get_wifi_self_steer_matching_bss_list(const char* ssid_to_find,wifi_neighbor_ap_t neighborAPList[], int timeout)
2171 {
2172  char tmpBuff[RETURN_BUF_LENGTH];
2173  int ap_count = 0;
2174  int retry = 0;
2175  int apCnt = 0,matchCount = 0;
2176 
2177  // initiate a scan and get the list of matching BSS
2178  WIFI_LOG_INFO( "Starting scan for best Neighbor SSIDs ... \n");
2179  bNoAutoScan = TRUE;
2180  pthread_mutex_lock(&wpa_sup_lock);
2181  wpaCtrlSendCmd("BSS_FLUSH 0");
2182  wpaCtrlSendCmd("SCAN");
2183  cur_scan_state = WIFI_HAL_WPA_SUP_SCAN_STATE_STARTED;
2184  pthread_mutex_unlock(&wpa_sup_lock);
2185 
2186  // Lets wait for the scan to complete
2187  while ((cur_scan_state != WIFI_HAL_WPA_SUP_SCAN_STATE_RESULTS_RECEIVED) &&(retry++ < 10)) {
2188  usleep(timeout*100000);
2189  }
2190  // Get scan results
2191  memset(tmpBuff,0,sizeof(tmpBuff));
2192  pthread_mutex_lock(&wpa_sup_lock);
2193  wpaCtrlSendCmd("SCAN_RESULTS");
2194  log_top5_bssids(return_buf);
2195  strncpy(tmpBuff,return_buf,sizeof(tmpBuff));
2196 
2197  // Parse scan result, So that global ap_list will be updated with new scan results
2198  ap_count = parse_scan_results (tmpBuff, strlen (tmpBuff));
2199  for(apCnt = 0;apCnt<ap_count; apCnt++) {
2200 
2201  if ((strncmp (ap_list[apCnt].ap_SSID,ssid_to_find,MAX_SSID_LEN) == 0) && (matchCount<MAX_NEIGHBOR_LIMIT)) {
2202  WIFI_LOG_INFO("SCAN Results Matching BSS - ssid = [%s] bssid = [%s] rssi = [%d] freq = [%s]\n",
2203  ap_list[apCnt].ap_SSID,ap_list[apCnt].ap_BSSID, ap_list[apCnt].ap_SignalStrength, ap_list[apCnt].ap_OperatingFrequencyBand);
2204  memcpy(&neighborAPList[matchCount],&ap_list[apCnt],sizeof(wifi_neighbor_ap_t));
2205  matchCount++;
2206  } else if(matchCount>=MAX_NEIGHBOR_LIMIT) {
2207  break;
2208  }
2209  }
2210  pthread_mutex_unlock(&wpa_sup_lock);
2211  return matchCount;
2212 }
2213 #ifdef WIFI_CLIENT_ROAMING
2214 static int get_best_ap_from_neighbor_list(wifi_neighbor_ap_t neighborAPList[],int apCount,wifi_neighbor_ap_t* bestNeighbor)
2215 {
2216  int count = 0;
2217  int retStatus = RETURN_ERR;
2218  wifi_neighbor_ap_t bestBss;
2219 
2220  if(apCount == 0) {
2221  WIFI_LOG_ERROR("BSS count is 0, Failed to get best AP from neighbor list.\n");
2222  return retStatus;
2223  }
2224  if(bestNeighbor == NULL) {
2225  WIFI_LOG_ERROR("Input neighbor struct is null, Failed to get best AP from neighbor list.\n");
2226  return retStatus;
2227  }
2228  memset(&bestBss,0,sizeof(wifi_neighbor_ap_t));
2229  for(count=0;count<apCount;count++) {
2230  if((bestBss.ap_SignalStrength == 0) || (bestBss.ap_SignalStrength < neighborAPList[count].ap_SignalStrength)) { // 1st entry
2231  memcpy(&bestBss,&neighborAPList[count],sizeof(wifi_neighbor_ap_t));
2232  }
2233  }
2234  if(bestBss.ap_SSID[0] != '\0') {
2235  memcpy(bestNeighbor,&bestBss,sizeof(wifi_neighbor_ap_t));
2236  WIFI_LOG_INFO( "Selecting best BSS [%s] with RSSI [%d] . \n",bestNeighbor->ap_BSSID,bestNeighbor->ap_SignalStrength);
2237  } else {
2238  WIFI_LOG_INFO( "Failed to get Best AP. !\n");
2239  }
2240  return RETURN_OK;
2241 }
2242 static int wifi_getRadioFrequencyFromChannel(int channel)
2243 {
2244 
2245  if (channel==14)
2246  return 2484;
2247  else if (channel<14)
2248  return (channel*5)+2407;
2249  else if (channel>=182 && channel<=196)
2250  return (channel*5)+4000;
2251  else if (channel>=36 && channel<=165)
2252  return (channel*5)+5000;
2253  else
2254  return 0;
2255 }
2256 
2257 static void incrementBackoff(int *backOff)
2258 {
2259  if(*backOff <= WIFI_MAX_POST_ASSN_BACKOFF_TIME) {
2260  *backOff = *backOff*2; // Increment only if it is less than Max backoff
2261  }
2262  return;
2263 }
2264 
2265 
2266 static int isWifiActivelyUsed()
2267 {
2268  return 1; // TODO: Get the value dynamically
2269 }
2270 static int start_post_assoc_roaming(WIFI_HAL_ROAMING_MODE roamingMode)
2271 {
2272  wifi_neighbor_ap_t neighborAPList[MAX_NEIGHBOR_LIMIT];
2273  int bssCount = 0;
2274  wifi_sta_stats_t currWifiStats;
2275  int radioIndex = 0;
2276  int retStatus = RETURN_ERR;
2277 
2278  memset(&neighborAPList,0,sizeof(neighborAPList));
2279  memset(&currWifiStats,0,sizeof(wifi_sta_stats_t));
2280 
2281  // Get the current stats params like ssid,bssid and rssi for current connection
2282  wifi_getStats(radioIndex, &currWifiStats);
2283  if(currWifiStats.sta_SSID[0] == '\0') {
2284  WIFI_LOG_ERROR("Failed to get current SSID, Skip Roaming. \n");
2285  return retStatus;
2286  }
2287  int timeout = 6; //6 seconds timeout
2288  pthread_mutex_lock(&wifi_roam_lock);
2289  cur_roaming_state = WIFI_HAL_ROAM_STATE_AP_SELECTION;
2290  pthread_mutex_unlock(&wifi_roam_lock);
2291  bssCount = get_wifi_self_steer_matching_bss_list(currWifiStats.sta_SSID,neighborAPList,timeout);
2292  if(bssCount == 0) {
2293  WIFI_LOG_ERROR("No Matching BSS found to Roam. \n");
2294  incrementBackoff(&postAssocBackOffTime);
2295  return retStatus;
2296  }
2297  WIFI_LOG_INFO("Got %d matching BSS for SSID %s \n",bssCount,currWifiStats.sta_SSID);
2298 
2299  int status;
2300  int rssiThreshold;
2301  int delta;
2302  wifi_neighbor_ap_t bestNeighbor;
2303 
2304  memset(&bestNeighbor,0,sizeof(wifi_neighbor_ap_t));
2305  if(roamingMode == WIFI_HAL_ROAMING_MODE_SELF_STEERING) {
2306  rssiThreshold = pstRoamingCtrl.postAssnSelfSteerThreshold;
2307  } else if (roamingMode == WIFI_HAL_ROAMING_MODE_AP_STEERING) {
2308  rssiThreshold = pstRoamingCtrl.postAssnAPctrlThreshold;
2309  }
2310 
2311  status = get_best_ap_from_neighbor_list(neighborAPList,bssCount,&bestNeighbor);
2312  // Check the validity of BSS
2313  if(status != RETURN_OK || (currWifiStats.sta_BSSID[0] == '\0') || (bestNeighbor.ap_BSSID[0] == '\0') ) {
2314  WIFI_LOG_ERROR("failed to get BSSID from Best BSS.\n");
2315  incrementBackoff(&postAssocBackOffTime);
2316  return retStatus;
2317  } else if(strncmp(currWifiStats.sta_BSSID,bestNeighbor.ap_BSSID,MAX_SSID_LEN-1) == 0) {
2318  WIFI_LOG_ERROR("Client is already connected to Best BSS, Skipping Roaming operation.\n");
2319  incrementBackoff(&postAssocBackOffTime);
2320  return retStatus;
2321  }
2322  // Valid BSS and Not the one already connected, Set Delta based on Wifi Activity
2323  if(isWifiActivelyUsed() == true) {
2324  delta = pstRoamingCtrl.postAssnLevelDeltaConnected; //Delta level connected
2325  } else {
2326  delta = pstRoamingCtrl.postAssnLevelDeltaDisconnected; // delta level disconnected
2327  }
2328  if(currWifiStats.sta_RSSI < bestNeighbor.ap_SignalStrength && ((bestNeighbor.ap_SignalStrength-(int)currWifiStats.sta_RSSI) >= delta)) {
2329  WIFI_LOG_INFO("Selected [%s] as best AP for SSID [%s] with RSSI [%d]. \n",bestNeighbor.ap_BSSID,bestNeighbor.ap_SSID,bestNeighbor.ap_SignalStrength);
2330  } else {
2331  WIFI_LOG_ERROR("Skipping roam to %s based on RSSI delta,Current RSSI=[%d],Target RSSI=[%d],Delta=[%d] \n",bestNeighbor.ap_BSSID,(int)currWifiStats.sta_RSSI,bestNeighbor.ap_SignalStrength,delta);
2332  incrementBackoff(&postAssocBackOffTime);
2333  return retStatus;
2334  }
2335  // Everything Looks good, Lets Roam to that BSSID
2336  char cmd[BUFF_LEN_64] = {0};
2337  sprintf(cmd,"ROAM %s",bestNeighbor.ap_BSSID);
2338  pthread_mutex_lock(&wpa_sup_lock);
2339  int roamStat = wpaCtrlSendCmd(cmd);
2340  pthread_mutex_unlock(&wpa_sup_lock);
2341  if(roamStat == RETURN_OK) {
2342  WIFI_LOG_INFO("WiFi ROAM: Roaming triggered to %s . \n",bestNeighbor.ap_BSSID);
2343  pthread_mutex_lock(&wifi_roam_lock);
2344  cur_roaming_state = WIFI_HAL_ROAM_STATE_ROAMING_TRIGGERED;
2345  pthread_mutex_unlock(&wifi_roam_lock);
2346  if(bestNeighbor.ap_SignalStrength >= pstRoamingCtrl.postAssnSelfSteerThreshold) {
2347  postAssocBackOffTime = pstRoamingCtrl.postAssnBackOffTime; // Roaming is successfull and connected to a good AP Lets reset Back off timer.
2348  backOffRefreshed = 1;
2349  WIFI_LOG_INFO("Successfully roamed to best AP.\n");
2350  } else {
2351  WIFI_LOG_INFO("Roaming is successful, But RSSI is still low. Increase Backoff\n");
2352  incrementBackoff(&postAssocBackOffTime);
2353  }
2354  retStatus = RETURN_OK;
2355  } else {
2356  WIFI_LOG_INFO("Failed to trigger ROAM operation. \n");
2357  incrementBackoff(&postAssocBackOffTime);
2358  }
2359  return retStatus;
2360 }
2361 
2362 /*
2363 * @Brief: Start APP steer Roaming based on 802.11k neighbor reports
2364 *
2365 */
2366 int start_ap_steer_roaming()
2367 {
2368  // Collect Neighbor Report, It will be already updated on wifi_rrm_neighbor_report_t stRrmNeighborRpt
2369  char freqList[BUFF_LEN_64];
2370  char cmd[BUFF_LEN_32];
2371  char freqStr[8];
2372  int apCount;
2373  int pos = 0;
2374  int status = 0;
2375 
2376  // Check if we have enough Neighbors
2377  memset(freqList,0,BUFF_LEN_64);
2378  memset(cmd,0,BUFF_LEN_32);
2379 
2380  // AP steer roaming, Update 802.11K neighbor report
2381  int isRRMSupported = wifi_get_rrm_support();
2382  if(isRRMSupported && (pstRoamingCtrl.roam80211kvrEnable == true)) {
2383  WIFI_LOG_INFO("RRM is enabled in current connection. trying to get Neighbor report. ! \n");
2384  wifi_rrm_neighbor_rep_request_t nbr_req;
2385  memset(&nbr_req,0,sizeof(wifi_rrm_neighbor_rep_request_t));
2386  memset(&stRrmNeighborRpt,0,sizeof(wifi_rrm_neighbor_report_t));
2387  cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_STATE_IDLE;
2388  int status = wifi_getRRMNeighborReport(&nbr_req,&stRrmNeighborRpt);
2389  if(status == RETURN_OK) {
2390  WIFI_LOG_INFO("Successfully sent request for RRM Neighbors. \n");
2391  } else {
2392  WIFI_LOG_ERROR("Failure in getting RRM Neighbor report. \n");
2393  }
2394  } else {
2395  WIFI_LOG_INFO("RRM is not supported or Not enabled. \n");
2396  }
2397 
2398  if(stRrmNeighborRpt.neighbor_cnt > 0 && (pstRoamingCtrl.roam80211kvrEnable == true)) {
2399  for(apCount=0;apCount<stRrmNeighborRpt.neighbor_cnt;apCount++) {
2400  // Remove duplicate frequency before adding to list
2401  memset(&freqStr,0,sizeof(freqStr));
2402  snprintf(freqStr,sizeof(freqStr),"%d",stRrmNeighborRpt.neighbor_ap->freq);
2403  if(strstr(freqList,freqStr) == NULL)
2404  pos += snprintf(&freqList[pos],BUFF_LEN_64," %s",freqStr);
2405  }
2406  WIFI_LOG_INFO("RRM, Setting scan Freq based on Neighbor report to - %s \n",freqList);
2407  snprintf(cmd,BUFF_LEN_32,"SET freq_list %s",freqList);
2408  pthread_mutex_lock(&wpa_sup_lock);
2409  wpaCtrlSendCmd(cmd);
2410  pthread_mutex_unlock(&wpa_sup_lock);
2411  } else {
2412  WIFI_LOG_INFO("802.11K Neighbor report not present, Scanning all channels for Roaming. \n");
2413  }
2414  start_post_assoc_roaming(WIFI_HAL_ROAMING_MODE_AP_STEERING);
2415 
2416  // Disable Freq List
2417  pthread_mutex_lock(&wpa_sup_lock);
2418  wpaCtrlSendCmd("SET freq_list 0");
2419  pthread_mutex_unlock(&wpa_sup_lock);
2420 }
2421 
2422 void start_wifi_signal_monitor_timer(void *arg)
2423 {
2424  int counter = 0;
2425  struct timespec to;
2426  struct timespec t;
2427  int rssiThreshold = 0;
2428  int timeIncrement = 0;
2429  static int prevTimeFrame = 0;
2430  int nextTimeFrame = 0;
2431 
2432  int timeFrame = (int*) arg;
2433  pthread_mutex_lock(&wifi_roam_lock);
2434  cur_roaming_state = WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_STARTED;
2435  pthread_mutex_unlock(&wifi_roam_lock);
2436  if(!backOffRefreshed) {
2437 
2438  // BackOff is not refreshed need to increment Time Frame
2439  if(postAssocBackOffTime > WIFI_MAX_POST_ASSN_BACKOFF_TIME) {
2440  nextTimeFrame = prevTimeFrame + postAssocBackOffTime/2;
2441  } else {
2442  nextTimeFrame = timeFrame + postAssocBackOffTime/2;
2443  }
2444  // Make sure that the next timeframe is within the limit.
2445  if(postAssocBackOffTime <= WIFI_MAX_POST_ASSN_BACKOFF_TIME && nextTimeFrame <= WIFI_MAX_POST_ASSN_TIME_FRAME) {
2446  timeFrame = nextTimeFrame;
2447  prevTimeFrame = timeFrame;
2448  } else if(nextTimeFrame <= WIFI_MAX_POST_ASSN_TIME_FRAME) {
2449  timeFrame = prevTimeFrame + postAssocBackOffTime/2;
2450  prevTimeFrame = timeFrame;
2451  } else {
2452  timeFrame = prevTimeFrame;
2453  }
2454  timeIncrement = postAssocBackOffTime/2;
2455 
2456  } else {
2457  backOffRefreshed = 0;
2458  prevTimeFrame = timeFrame;
2459  }
2460 
2461  WIFI_LOG_INFO("Starting signal monitor thread, TimeFrame = %d with Backoff = %d.\n",timeFrame,timeIncrement);
2462  clock_gettime(CLOCK_MONOTONIC, &to);
2463  to.tv_sec += timeFrame;
2464  int retVal = -1;
2465  pthread_mutex_lock(&wifi_roam_lock);
2466  if((retVal = pthread_cond_timedwait(&cond,&wifi_roam_lock,&to)) == 0) {
2467  WIFI_LOG_INFO("Signal strength recovered or connection state changed, lets stop roaming timer. !\n");
2468  cur_roaming_state = WIFI_HAL_ROAM_STATE_ROAMING_IDLE;
2469  pthread_mutex_unlock(&wifi_roam_lock);
2470  }
2471  else if(retVal == ETIMEDOUT) {
2472  WIFI_LOG_INFO("Signal monitor timer expired, RSSI is still lower, trigger roaming operation.\n");
2473  cur_roaming_state = WIFI_HAL_ROAM_STATE_THRESHOLD_TIMER_EXPIRED;
2474  pthread_mutex_unlock(&wifi_roam_lock);
2475  if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_SELF_STEERING) {
2476  WIFI_LOG_INFO("Starting Self steer roaming... \n");
2477  start_post_assoc_roaming(WIFI_HAL_ROAMING_MODE_SELF_STEERING);
2478  rssiThreshold = pstRoamingCtrl.postAssnSelfSteerThreshold;
2479  } else if(cur_roaming_mode == WIFI_HAL_ROAMING_MODE_AP_STEERING){
2480  WIFI_LOG_INFO("Starting AP-Controlled roaming... \n");
2481  start_ap_steer_roaming();
2482  rssiThreshold = pstRoamingCtrl.postAssnAPctrlThreshold;
2483  } else {
2484  WIFI_LOG_ERROR("Unrecognized roaming mode, skipping Roaming operation.\n");
2485  }
2486  // Refresh signal_monitor
2487  wifi_set_signal_monitor(rssiThreshold);
2488  } else {
2489  WIFI_LOG_ERROR("Wifi Roam conditional wait failed.! \n");
2490  pthread_mutex_unlock(&wifi_roam_lock);
2491  }
2492  pthread_mutex_lock(&wifi_roam_lock);
2493  cur_roaming_state = WIFI_HAL_ROAM_STATE_ROAMING_IDLE;
2494  pthread_mutex_unlock(&wifi_roam_lock);
2495 }
2496 
2497 int wifi_get_rrm_support()
2498 {
2499  int retStatus = 0;
2500  int rrmSupport = 0;
2501 
2502  // Get RRM Support using wpa_cli command
2503  pthread_mutex_lock(&wpa_sup_lock);
2504  retStatus = wpaCtrlSendCmd("GET_RRM_SUPPORT");
2505  if(retStatus == RETURN_OK && return_buf[0] != '\0' ) {
2506  rrmSupport = strtol(return_buf,NULL,10);
2507  } else {
2508  WIFI_LOG_ERROR("Failed to get RRM support.\n");
2509  }
2510  pthread_mutex_unlock(&wpa_sup_lock);
2511  return rrmSupport;
2512 }
2513 
2514 /**
2515  * @brief This API Gets the 802.11K Neighbor report from the Associated Accesspoint by sending Neighbor request.
2516  *
2517  * @param[in] nbr_req - Neighbor report request structure
2518  * @param[out] nbr_rpt - Neighbor report structure
2519  *
2520  * @return The status of the operation.
2521  * @retval RETURN_OK returns O if successful, appropriate error code otherwise.
2522  */
2523 INT wifi_getRRMNeighborReport(wifi_rrm_neighbor_rep_request_t* nbr_req, wifi_rrm_neighbor_report_t* nbr_rpt)
2524 {
2525  int retStatus = RETURN_ERR;
2526  int retry;
2527  char bssid[32];
2528  int ssidIndex=1;
2529 
2530  // Check if the client is Associated by checking the current bssid.
2531  memset(bssid,0,sizeof(bssid));
2532  if(wifi_getBaseBSSID(ssidIndex, bssid) == RETURN_ERR || bssid[0] == '\0') {
2533  WIFI_LOG_ERROR("Client is not associated, RRM request failed.\n");
2534  return retStatus;
2535  }
2536 
2537  retStatus = wifi_sendNeighborReportRequest(nbr_req);
2538  if(retStatus == 0) {
2539  retry = 0;
2540  // Wait Max of 1 seconds for getting RRM event
2541  while (((cur_rrm_nbr_rep_state != WIFI_HAL_RRM_NEIGHBOR_REP_RECEIVED)) &&(retry++ < 10)) {
2542  usleep(100000);
2543  }
2544  if(retry >= 10) {
2545  WIFI_LOG_ERROR("Failed to get RRM response, Request timed out.!\n");
2546  } else if(cur_rrm_nbr_rep_state == WIFI_HAL_RRM_NEIGHBOR_REP_REQUEST_FAILED) {
2547  WIFI_LOG_ERROR("RRM neighbor report request failed.\n");
2548  } else if (cur_rrm_nbr_rep_state == WIFI_HAL_RRM_NEIGHBOR_REP_STATE_INTERNAL_ERROR) {
2549  WIFI_LOG_ERROR("RRM neighbor report report received, But failed to parse.\n");
2550  } else if (cur_rrm_nbr_rep_state == WIFI_HAL_RRM_NEIGHBOR_REP_RECEIVED) {
2551  WIFI_LOG_INFO("RRM Neighbor report succesfully received.\n");
2552  //memcpy(nbr_rpt,&stRrmNeighborRpt,sizeof(wifi_rrm_neighbor_report_t));
2553  retStatus = RETURN_OK;
2554  }
2555  } else {
2556  WIFI_LOG_ERROR("Failed to send RRM Neighbor Request. \n");
2557  }
2558  cur_rrm_nbr_rep_state = WIFI_HAL_RRM_NEIGHBOR_REP_STATE_IDLE;
2559  return retStatus;
2560 }
2561 
2562 /**
2563  * @brief This API sends the 802.11K Neighbor report request to the Associated Accesspoint.
2564  *
2565  * @param[in] nbr_req - Neighbor report request structure
2566  *
2567  * @return The status of the operation.
2568  * @retval RETURN_OK returns O if successful, appropriate error code otherwise.
2569  */
2570 INT wifi_sendNeighborReportRequest(wifi_rrm_neighbor_rep_request_t* nbr_req)
2571 {
2572  char cmd[BUFF_LEN_64];
2573  int retStatus = RETURN_ERR;
2574 
2575  memset(cmd,0,BUFF_LEN_64);
2576 
2577  if(nbr_req->ssid[0] != '\0') {
2578  WIFI_LOG_DEBUG("Sending RRM neighbor request with ssid=%s, lci=%d, civic=%d \n",nbr_req->ssid,nbr_req->lci,nbr_req->civic);
2579  snprintf(cmd,sizeof(cmd),"NEIGHBOR_REP_REQUEST ssid=\"%s\" lci=%d civic=%d",nbr_req->ssid,nbr_req->lci,nbr_req->civic);
2580  } else {
2581  snprintf(cmd,sizeof(cmd),"NEIGHBOR_REP_REQUEST");
2582  }
2583  pthread_mutex_lock(&wpa_sup_lock);
2584  retStatus = wpaCtrlSendCmd(cmd);
2585  pthread_mutex_unlock(&wpa_sup_lock);
2586  if(retStatus == 0) {
2587  WIFI_LOG_INFO("RRM Neighbor report request sent successfully \n");
2588  retStatus = RETURN_OK;
2589  } else {
2590  WIFI_LOG_ERROR("Failed to send RRM Request, cmd = %s \n",cmd);
2591  }
2592  return retStatus;
2593 }
2594 
2595 /**
2596  * @brief This API sends the 802.11K Neighbor report request to the Associated Accesspoint.
2597  *
2598  * @param[in] nbr_response - Neighbor response buffer from wpa_supplicant event buffer
2599  * @param[in] nbr_rpt - Neighbor report structure
2600  *
2601  * @return The status of the operation.
2602  * @retval RETURN_OK returns O if successful, appropriate error code otherwise.
2603  */
2604 int parse_neighbor_report_response(char *nbr_response,wifi_rrm_neighbor_report_t *nbr_rpt)
2605 {
2606 
2607  char bssid[BUFF_LEN_32];
2608  char info[BUFF_LEN_32];
2609  int op_class,channel,phy_type;
2610 
2611  if(!nbr_response || nbr_response[0] == '\0') {
2612  WIFI_LOG_ERROR("Unable to parse - Neighbor response is NULL. \n");
2613  return RETURN_ERR;
2614  } else if(!nbr_rpt) {
2615  WIFI_LOG_ERROR("Unable to parse - Input Neighbor report is NULL \n");
2616  return RETURN_ERR;
2617  }
2618 
2619  // Sample Response Pattern
2620  //<3>RRM-NEIGHBOR-REP-RECEIVED bssid=ec:aa:a0:81:7f:20 info=0x1801 op_class=0 chan=153 phy_type=1 lci=0100080010000000000000000000000000000000000406000000000000060101 civic=02000b0000ed000000
2621  if(sscanf(nbr_response,"%*s bssid=%s info=%s op_class=%d chan=%d phy_type=%d",bssid,info,&op_class,&channel,&phy_type) == 5) {
2622  int i;
2623  int match = 0;
2624  // Check if the bssid is already present in list
2625  for(i=0;i<nbr_rpt->neighbor_cnt;i++) {
2626  if(strncmp(nbr_rpt->neighbor_ap[i].bssid,bssid,MAX_SSID_LEN) == 0) {
2627  match = 1;
2628  break;
2629  }
2630  }
2631  if(!match && (nbr_rpt->neighbor_cnt < MAX_NEIGHBOR_LIMIT)) {
2632  strncpy(nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].bssid,bssid,sizeof(nbr_rpt->neighbor_ap->bssid));
2633  strncpy(nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].bssidInfo,info,sizeof(nbr_rpt->neighbor_ap->bssidInfo));
2634  nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].channel = channel;
2635  nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].op_class = op_class;
2636  nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].phy_type = phy_type;
2637  nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].freq = wifi_getRadioFrequencyFromChannel(channel);
2638  WIFI_LOG_INFO("RRM Neighbor[%d] - Bssid = %s , Info = %s, op_class=%d, Channel = %d, Phy_Type = %d, Freq=%d\n ",nbr_rpt->neighbor_cnt,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].bssid,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].bssidInfo,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].op_class,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].channel,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].phy_type,nbr_rpt->neighbor_ap[nbr_rpt->neighbor_cnt].freq);
2639  nbr_rpt->neighbor_cnt+=1;
2640  } else if(match){
2641  WIFI_LOG_INFO("BSSID already present in neighbor list, Skipping %s \n",bssid);
2642  } else {
2643  WIFI_LOG_INFO("Maximum neighbors added to list, Skipping.\n");
2644  }
2645  } else {
2646  WIFI_LOG_INFO("Failed to Parse Neighbor Report - Skipping entry\n");
2647  }
2648  return RETURN_OK;
2649 }
2650 #endif // WIFI_CLIENT_ROAMING
2651 
2652 WiFiHalStatus_t getwifiStatusCode()
2653 {
2654  return WIFISTATUS_HAL_COMPLETED;
2655 }
2656 
2657 void wifi_printf(const char *level, const char *format, ...)
2658 {
2659  va_list arg_list;
2660 
2661  struct timeval now;
2662  gettimeofday(&now, NULL);
2663  printf("[%6s] %9ld.%06ld - ", level, now.tv_sec, now.tv_usec);
2664 
2665  va_start(arg_list, format);
2666  vprintf(format, arg_list);
2667  va_end(arg_list);
2668 }
WIFI_SECURITY_WPA_ENTERPRISE_TKIP
@ WIFI_SECURITY_WPA_ENTERPRISE_TKIP
WPA Enterprise with TKIP (Temporal Key Integrity Protocol) encryption.
Definition: wifi_common_hal.h:329
WIFI_HAL_ERROR_SSID_CHANGED
@ WIFI_HAL_ERROR_SSID_CHANGED
Definition: wifi_common_hal.h:299
wifi_getCliWpsConfigMethodsEnabled
INT wifi_getCliWpsConfigMethodsEnabled(INT ssidIndex, CHAR *output_string)
This function indicates WPS configuration methods enabled on the device.
Definition: wifi_client_hal.c:909
wifi_getCliWpsConfigurationState
INT wifi_getCliWpsConfigurationState(INT ssidIndex, CHAR *output_string)
This API is used to get the WPS config status, whether "configured" or "not configured".
Definition: wifi_client_hal.c:931
wifi_setCliWpsEnrolleePin
INT wifi_setCliWpsEnrolleePin(INT ssidIndex, CHAR *wps_pin)
This API sets the PIN to connect. User get the EnrolleePin (device pin from AP device) give to hostap...
Definition: wifi_client_hal.c:937
wifi_lastConnected_Endpoint
INT wifi_lastConnected_Endpoint(wifi_pairedSSIDInfo_t *pairedSSIDInfo)
This call will give the last saved AP's ssid.
Definition: wifi_client_hal.c:1555
_wifi_sta_stats::sta_SSID
char sta_SSID[64]
The current connected SSID name.
Definition: wifi_common_hal.h:457
RETURN_OK
#define RETURN_OK
Defines for function returns.
Definition: wifi_common_hal.h:218
WIFI_HAL_ERROR_CONNECTION_FAILED
@ WIFI_HAL_ERROR_CONNECTION_FAILED
Definition: wifi_common_hal.h:301
WIFI_HAL_CONNECTING
@ WIFI_HAL_CONNECTING
Definition: wifi_common_hal.h:292
_wifi_sta_stats::sta_BSSID
char sta_BSSID[64]
The BSSID used for connected SSID.
Definition: wifi_common_hal.h:458
wifiSecurityMode_t
wifiSecurityMode_t
Wifi Security modes.
Definition: wifi_common_hal.h:320
_wifi_pairedSSIDInfo::ap_wep_key
CHAR ap_wep_key[128]
wep_key of AP incase of WEP security
Definition: wifi_client_hal.h:125
wifi_getCliWpsEnable
INT wifi_getCliWpsEnable(INT ssidIndex, BOOL *output_bool)
This API checks WPS(Wi-Fi Protected Setup) functionality is enabled for this access point.
Definition: wifi_client_hal.c:867
_wifi_pairedSSIDInfo::ap_bssid
CHAR ap_bssid[64]
[MACAddress] The BSSID (Basic Service Set ID) used for the neighboring WiFi SSID.
Definition: wifi_client_hal.h:122
_wifi_pairedSSIDInfo::ap_security
CHAR ap_security[64]
Security of AP.
Definition: wifi_client_hal.h:123
WIFI_SECURITY_WPA3_SAE
@ WIFI_SECURITY_WPA3_SAE
WPA3 with SAE encryption.
Definition: wifi_common_hal.h:336
_wifi_wps_pbc_ap
Definition: wifi_client_hal.c:145
wifi_setCliWpsDevicePIN
INT wifi_setCliWpsDevicePIN(INT ssidIndex, ULONG pin)
This API sets the WPS Device pin to the Wi-Fi hal.
Definition: wifi_client_hal.c:882
_wifi_telemetry_ops_t
Telemetry callback functions.
Definition: wifi_client_hal.h:378
wifi_connectEndpoint
INT wifi_connectEndpoint(INT ssidIndex, CHAR *AP_SSID, wifiSecurityMode_t AP_security_mode, CHAR *AP_security_WEPKey, CHAR *AP_security_PreSharedKey, CHAR *AP_security_KeyPassphrase, int saveSSID, CHAR *eapIdentity, CHAR *carootcert, CHAR *clientcert, CHAR *privatekey)
This API starts the connection process from client with an AP.
Definition: wifi_client_hal.c:1348
WIFI_SECURITY_WPA2_ENTERPRISE_AES
@ WIFI_SECURITY_WPA2_ENTERPRISE_AES
WPA2 Enterprise with AES (Advanced Encryption Standard) encryption.
Definition: wifi_common_hal.h:332
wifi_getBaseBSSID
int wifi_getBaseBSSID(int ssidIndex, char *output_string)
Get the BSSID. Basic Service Set Identifier (BSSID) is the mac addresss of the wireless access point.
_wifi_pairedSSIDInfo::ap_ssid
CHAR ap_ssid[64]
The current service set identifier in use by the neighboring WiFi SSID. The value MAY be empty for hi...
Definition: wifi_client_hal.h:121
wifi_getCliWpsConfigMethodsSupported
INT wifi_getCliWpsConfigMethodsSupported(INT ssidIndex, CHAR *methods)
This API is used to get WPS configuration methods supported by the device.
Definition: wifi_client_hal.c:896
wifi_telemetry_callback_register
void wifi_telemetry_callback_register(wifi_telemetry_ops_t *telemetry_ops)
Definition: wifi_client_hal.c:250
_wifi_neighbor_ap::ap_BSSID
char ap_BSSID[64]
[MACAddress] The BSSID used for the neighboring WiFi SSID.
Definition: wifi_common_hal.h:413
_wifi_pairedSSIDInfo::ap_passphrase
CHAR ap_passphrase[128]
Passphrase of AP.
Definition: wifi_client_hal.h:124
_wifi_roamingCtrl_t
Roaming Control information (pre assoc data structure}.
Definition: wifi_client_hal.h:135
WIFI_HAL_SUCCESS
@ WIFI_HAL_SUCCESS
Definition: wifi_common_hal.h:291
WIFI_SECURITY_WPA_WPA2_PSK
@ WIFI_SECURITY_WPA_WPA2_PSK
WPA2(Pre-Shared Key) with TKIP AES encryption.
Definition: wifi_common_hal.h:333
ULONG
#define ULONG
Defines for the basic data types.
Definition: wifi_common_hal.h:168
wifi_getCliWpsDevicePIN
INT wifi_getCliWpsDevicePIN(INT ssidIndex, ULONG *output_ulong)
This API is used to read the device PIN required for making a WPS connection.
Definition: wifi_client_hal.c:877
WIFI_SECURITY_WPA2_ENTERPRISE_TKIP
@ WIFI_SECURITY_WPA2_ENTERPRISE_TKIP
WPA2 Enterprise with TKIP (Temporal Key Integrity Protocol) encryption.
Definition: wifi_common_hal.h:331
WIFI_SECURITY_WPA_PSK_TKIP
@ WIFI_SECURITY_WPA_PSK_TKIP
WPA(Pre-Shared Key) with TKIP (Temporal Key Integrity Protocol) encryption.
Definition: wifi_common_hal.h:325
wifi_setCliWpsButtonPush
INT wifi_setCliWpsButtonPush(INT ssidIndex)
Start the Push button pairing.
Definition: wifi_client_hal.c:1295
WIFI_SECURITY_WPA2_PSK_TKIP
@ WIFI_SECURITY_WPA2_PSK_TKIP
WPA2(Pre-Shared Key) with TKIP (Temporal Key Integrity Protocol) encryption.
Definition: wifi_common_hal.h:327
wifi_connectEndpoint_callback
INT(* wifi_connectEndpoint_callback)(INT ssidIndex, CHAR *AP_SSID, wifiStatusCode_t *error)
This call back will be invoked when client automatically connect to Access Point.
Definition: wifi_client_hal.h:366
wifi_disconnectEndpoint_callback
INT(* wifi_disconnectEndpoint_callback)(INT ssidIndex, CHAR *AP_SSID, wifiStatusCode_t *error)
This call back should be registered by Wi-Fi manager to receive status updates from HAL in case of a ...
Definition: wifi_client_hal.h:347
wifi_disconnectEndpoint
INT wifi_disconnectEndpoint(INT ssidIndex, CHAR *AP_SSID)
This API disconnects the access point specified.
Definition: wifi_client_hal.c:1666
WIFI_HAL_ERROR_INVALID_CREDENTIALS
@ WIFI_HAL_ERROR_INVALID_CREDENTIALS
Definition: wifi_common_hal.h:303
_wifi_neighbor_ap
Definition: wifi_common_hal.h:409
WIFI_SECURITY_WPA_ENTERPRISE_AES
@ WIFI_SECURITY_WPA_ENTERPRISE_AES
WPA Enterprise with AES (Advanced Encryption Standard) encryption.
Definition: wifi_common_hal.h:330
WIFI_SECURITY_WPA2_PSK_AES
@ WIFI_SECURITY_WPA2_PSK_AES
WPA2(Pre-Shared Key) with AES (Advanced Encryption Standard) encryption.
Definition: wifi_common_hal.h:328
wifi_setCliWpsEnable
INT wifi_setCliWpsEnable(INT ssidIndex, BOOL enableValue)
This API enables or disables WPS functionality for this access point.
Definition: wifi_client_hal.c:872
wifi_getStats
void wifi_getStats(int radioIndex, wifi_sta_stats_t *wifi_sta_stats)
Returns current station connection status.
_wifi_pairedSSIDInfo
SSID information.
Definition: wifi_client_hal.h:119
WIFI_SECURITY_WEP_64
@ WIFI_SECURITY_WEP_64
WEP with 64 bit encryption.
Definition: wifi_common_hal.h:323
_wifi_sta_stats::sta_RSSI
float sta_RSSI
RSSI value in dBm.
Definition: wifi_common_hal.h:464
wifi_connectEndpoint_callback_register
void wifi_connectEndpoint_callback_register(wifi_connectEndpoint_callback callback_proc)
Callback registration function.
Definition: wifi_client_hal.c:238
WIFI_HAL_ERROR_AUTH_FAILED
@ WIFI_HAL_ERROR_AUTH_FAILED
Definition: wifi_common_hal.h:305
wifi_setCliWpsConfigMethodsEnabled
INT wifi_setCliWpsConfigMethodsEnabled(INT ssidIndex, CHAR *methodString)
This API sets the active WPS method.
Definition: wifi_client_hal.c:920
WIFI_SECURITY_WPA3_PSK_AES
@ WIFI_SECURITY_WPA3_PSK_AES
WPA3(Pre-Shared Key) with AES encryption.
Definition: wifi_common_hal.h:335
_wifi_neighbor_ap::ap_SSID
char ap_SSID[64]
The current service set identifier in use by the neighboring WiFi SSID. The value MAY be empty for hi...
Definition: wifi_common_hal.h:412
_wifi_sta_stats
Definition: wifi_common_hal.h:455
wifi_disconnectEndpoint_callback_register
void wifi_disconnectEndpoint_callback_register(wifi_disconnectEndpoint_callback callback_proc)
Callback registration function.
Definition: wifi_client_hal.c:244
WIFI_SECURITY_WEP_128
@ WIFI_SECURITY_WEP_128
WEP with 128 bit encryption.
Definition: wifi_common_hal.h:324
_wifi_neighbor_ap::ap_SignalStrength
int ap_SignalStrength
An indicator of radio signal strength (RSSI) of the neighboring WiFi radio measured in&#160;dBm,...
Definition: wifi_common_hal.h:416
WIFI_SECURITY_WPA_WPA2_ENTERPRISE
@ WIFI_SECURITY_WPA_WPA2_ENTERPRISE
WPA,WPA2 Enterprise with TKIP AES encryption.
Definition: wifi_common_hal.h:334
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
WIFI_SECURITY_WPA_PSK_AES
@ WIFI_SECURITY_WPA_PSK_AES
WPA(Pre-Shared Key) with AES (Advanced Encryption Standard) encryption.
Definition: wifi_common_hal.h:326
WIFI_HAL_ERROR_NOT_FOUND
@ WIFI_HAL_ERROR_NOT_FOUND
Definition: wifi_common_hal.h:296
wifiStatusCode_t
wifiStatusCode_t
Enumerators for Wi-Fi connection status.
Definition: wifi_common_hal.h:290