1#include <stdint.h>
2#include <stdlib.h>
3
4#include "wifi_hal.h"
5
6#define LOG_TAG  "WifiHAL"
7
8#include <utils/Log.h>
9#include <inttypes.h>
10#include <sys/socket.h>
11#include <linux/if.h>
12#include <ctype.h>
13#include <stdarg.h>
14
15pthread_mutex_t printMutex;
16void printMsg(const char *fmt, ...)
17{
18    pthread_mutex_lock(&printMutex);
19    va_list l;
20    va_start(l, fmt);
21
22    vprintf(fmt, l);
23    va_end(l);
24    pthread_mutex_unlock(&printMutex);
25}
26
27template<typename T, unsigned N>
28unsigned countof(T (&rgt)[N]) {
29    return N;
30}
31
32template<typename T>
33T min(const T& t1, const T& t2) {
34    return (t1 < t2) ? t1 : t2;
35}
36
37#define EVENT_BUF_SIZE 2048
38#define MAX_CH_BUF_SIZE  64
39#define MAX_FEATURE_SET  8
40#define HOTLIST_LOST_WINDOW  5
41
42static wifi_handle halHandle;
43static wifi_interface_handle *ifaceHandles;
44static wifi_interface_handle wlan0Handle;
45static wifi_interface_handle p2p0Handle;
46static int numIfaceHandles;
47static int cmdId = 0;
48static int ioctl_sock = 0;
49static int max_event_wait = 5;
50static int stest_max_ap = 10;
51static int stest_base_period = 5000;
52static int stest_threshold = 80;
53static int swctest_rssi_sample_size =  3;
54static int swctest_rssi_lost_ap =  3;
55static int swctest_rssi_min_breaching =  2;
56static int swctest_rssi_ch_threshold =  1;
57static int htest_low_threshold =  90;
58static int htest_high_threshold =  10;
59static int rtt_samples = 30;
60static wifi_band band = WIFI_BAND_UNSPECIFIED;
61
62mac_addr hotlist_bssids[16];
63unsigned char mac_oui[3];
64int channel_list[16];
65int num_hotlist_bssids = 0;
66int num_channels = 0;
67
68void parseMacAddress(const char *str, mac_addr addr);
69
70int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
71{
72    struct ifreq ifr;
73    int ret;
74
75    printMsg("setting interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
76
77    if (sock < 0) {
78      printMsg("Bad socket: %d\n", sock);
79      return -1;
80    }
81
82    memset(&ifr, 0, sizeof(ifr));
83    strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
84
85    printMsg("reading old value\n");
86
87    if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
88      ret = errno ? -errno : -999;
89      printMsg("Could not read interface %s flags: %d\n", ifname, errno);
90      return ret;
91    }else {
92      printMsg("writing new value\n");
93    }
94
95    if (dev_up) {
96      if (ifr.ifr_flags & IFF_UP) {
97        printMsg("interface %s is already up\n", ifname);
98        return 0;
99      }
100      ifr.ifr_flags |= IFF_UP;
101    }else {
102      if (!(ifr.ifr_flags & IFF_UP)) {
103        printMsg("interface %s is already down\n", ifname);
104        return 0;
105      }
106      ifr.ifr_flags &= ~IFF_UP;
107    }
108
109    if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
110      printMsg("Could not set interface %s flags \n", ifname);
111      return ret;
112    }else {
113      printMsg("set interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
114    }
115    printMsg("Done\n");
116    return 0;
117}
118
119
120static int init() {
121
122    ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
123    if (ioctl_sock < 0) {
124      printMsg("Bad socket: %d\n", ioctl_sock);
125      return errno;
126    } else {
127      printMsg("Good socket: %d\n", ioctl_sock);
128    }
129
130    int ret = linux_set_iface_flags(ioctl_sock, "wlan0", 1);
131    if (ret < 0) {
132        return ret;
133    }
134
135    wifi_error res = wifi_initialize(&halHandle);
136    if (res < 0) {
137        return res;
138    }
139
140    res = wifi_get_ifaces(halHandle, &numIfaceHandles, &ifaceHandles);
141    if (res < 0) {
142        return res;
143    }
144
145    char buf[EVENT_BUF_SIZE];
146    for (int i = 0; i < numIfaceHandles; i++) {
147        if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
148            if (strcmp(buf, "wlan0") == 0) {
149                printMsg("found interface %s\n", buf);
150                wlan0Handle = ifaceHandles[i];
151            } else if (strcmp(buf, "p2p0") == 0) {
152                printMsg("found interface %s\n", buf);
153                p2p0Handle = ifaceHandles[i];
154            }
155        }
156    }
157
158    return res;
159}
160
161static void cleaned_up_handler(wifi_handle handle) {
162    printMsg("HAL cleaned up handler\n");
163    halHandle = NULL;
164    ifaceHandles = NULL;
165}
166
167static void cleanup() {
168    printMsg("cleaning up HAL\n");
169    wifi_cleanup(halHandle, cleaned_up_handler);
170}
171
172static void *eventThreadFunc(void *context) {
173
174    printMsg("starting wifi event loop\n");
175    wifi_event_loop(halHandle);
176    printMsg("out of wifi event loop\n");
177
178    return NULL;
179}
180
181
182static int getNewCmdId() {
183    return cmdId++;
184}
185
186/* -------------------------------------------  */
187/* helpers                                      */
188/* -------------------------------------------  */
189
190void printScanHeader() {
191    printMsg("SSID\t\t\t\t\tBSSID\t\t  RSSI\tchannel\ttimestamp\tRTT\tRTT SD\n");
192}
193
194void printScanResult(wifi_scan_result result) {
195
196    printMsg("%-32s\t", result.ssid);
197
198    printMsg("%02x:%02x:%02x:%02x:%02x:%02x ", result.bssid[0], result.bssid[1],
199            result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
200
201    printMsg("%d\t", result.rssi);
202    printMsg("%d\t", result.channel);
203    printMsg("%lld\t", result.ts);
204    printMsg("%lld\t", result.rtt);
205    printMsg("%lld\n", result.rtt_sd);
206}
207
208void printSignificantChangeResult(wifi_significant_change_result *res) {
209
210    wifi_significant_change_result &result = *res;
211    printMsg("%02x:%02x:%02x:%02x:%02x:%02x ", result.bssid[0], result.bssid[1],
212            result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
213
214    printMsg("%d\t", result.channel);
215
216    for (int i = 0; i < result.num_rssi; i++) {
217        printMsg("%d,", result.rssi[i]);
218    }
219    printMsg("\n");
220}
221
222void printScanCapabilities(wifi_gscan_capabilities capabilities)
223{
224    printMsg("max_scan_cache_size = %d\n", capabilities.max_scan_cache_size);
225    printMsg("max_scan_buckets = %d\n", capabilities.max_scan_buckets);
226    printMsg("max_ap_cache_per_scan = %d\n", capabilities.max_ap_cache_per_scan);
227    printMsg("max_rssi_sample_size = %d\n", capabilities.max_rssi_sample_size);
228    printMsg("max_scan_reporting_threshold = %d\n", capabilities.max_scan_reporting_threshold);
229    printMsg("max_hotlist_aps = %d\n", capabilities.max_hotlist_aps);
230    printMsg("max_significant_wifi_change_aps = %d\n",
231    capabilities.max_significant_wifi_change_aps);
232}
233
234
235/* -------------------------------------------  */
236/* commands and events                          */
237/* -------------------------------------------  */
238
239typedef enum {
240    EVENT_TYPE_SCAN_RESULTS_AVAILABLE = 1000,
241    EVENT_TYPE_HOTLIST_AP_FOUND = 1001,
242    EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE = 1002,
243    EVENT_TYPE_RTT_RESULTS = 1003,
244    EVENT_TYPE_SCAN_COMPLETE = 1004,
245    EVENT_TYPE_HOTLIST_AP_LOST = 1005
246} EventType;
247
248typedef struct {
249    int type;
250    char buf[256];
251} EventInfo;
252
253const int MAX_EVENTS_IN_CACHE = 256;
254EventInfo eventCache[256];
255int eventsInCache = 0;
256pthread_cond_t eventCacheCondition;
257pthread_mutex_t eventCacheMutex;
258
259void putEventInCache(int type, const char *msg) {
260    pthread_mutex_lock(&eventCacheMutex);
261    if (eventsInCache + 1 < MAX_EVENTS_IN_CACHE) {
262        eventCache[eventsInCache].type = type;
263        strcpy(eventCache[eventsInCache].buf, msg);
264        eventsInCache++;
265        pthread_cond_signal(&eventCacheCondition);
266        //printf("put new event in cache; size = %d\n", eventsInCache);
267    } else {
268        printf("Too many events in the cache\n");
269    }
270    pthread_mutex_unlock(&eventCacheMutex);
271}
272
273void getEventFromCache(EventInfo& info) {
274    pthread_mutex_lock(&eventCacheMutex);
275    while (true) {
276        if (eventsInCache > 0) {
277            //printf("found an event in cache; size = %d\n", eventsInCache);
278            info.type = eventCache[0].type;
279            strcpy(info.buf, eventCache[0].buf);
280            eventsInCache--;
281            memmove(&eventCache[0], &eventCache[1], sizeof(EventInfo) * eventsInCache);
282            pthread_mutex_unlock(&eventCacheMutex);
283            return;
284        } else {
285            pthread_cond_wait(&eventCacheCondition, &eventCacheMutex);
286            //printf("pthread_cond_wait unblocked ...\n");
287        }
288    }
289}
290
291int numScanResultsAvailable = 0;
292static void onScanResultsAvailable(wifi_request_id id, unsigned num_results) {
293    printMsg("Received scan results available event\n");
294    numScanResultsAvailable = num_results;
295    putEventInCache(EVENT_TYPE_SCAN_RESULTS_AVAILABLE, "New scan results are available");
296}
297
298static void on_scan_event(wifi_scan_event event, unsigned status) {
299    if (event == WIFI_SCAN_BUFFER_FULL) {
300        printMsg("Received scan complete event - WIFI_SCAN_BUFFER_FULL \n");
301    } else if(event == WIFI_SCAN_COMPLETE) {
302        printMsg("Received scan complete event  - WIFI_SCAN_COMPLETE\n");
303    }
304}
305
306static int scanCmdId;
307static int hotlistCmdId;
308static int significantChangeCmdId;
309static int rttCmdId;
310
311static bool startScan( void (*pfnOnResultsAvailable)(wifi_request_id, unsigned),
312                       int max_ap_per_scan, int base_period, int report_threshold) {
313
314    /* Get capabilties */
315    wifi_gscan_capabilities capabilities;
316    int result = wifi_get_gscan_capabilities(wlan0Handle, &capabilities);
317    if (result < 0) {
318        printMsg("failed to get scan capabilities - %d\n", result);
319        printMsg("trying scan anyway ..\n");
320    } else {
321        printScanCapabilities(capabilities);
322    }
323
324    wifi_scan_cmd_params params;
325    memset(&params, 0, sizeof(params));
326
327    if(num_channels > 0){
328        params.max_ap_per_scan = max_ap_per_scan;
329        params.base_period = base_period;                      // 5 second by default
330        params.report_threshold = report_threshold;
331        params.num_buckets = 1;
332
333        params.buckets[0].bucket = 0;
334        params.buckets[0].band = WIFI_BAND_UNSPECIFIED;
335        params.buckets[0].period = base_period;
336        params.buckets[0].num_channels = num_channels;
337
338        for(int i = 0; i < num_channels; i++){
339            params.buckets[0].channels[i].channel = channel_list[i];
340        }
341
342    } else {
343
344        /* create a schedule to scan channels 1, 6, 11 every 5 second and
345         * scan 36, 40, 44, 149, 153, 157, 161 165 every 10 second */
346
347      params.max_ap_per_scan = max_ap_per_scan;
348      params.base_period = base_period;                      // 5 second
349      params.report_threshold = report_threshold;
350      params.num_buckets = 3;
351
352      params.buckets[0].bucket = 0;
353      params.buckets[0].band = WIFI_BAND_UNSPECIFIED;
354      params.buckets[0].period = 5000;                // 5 second
355      params.buckets[0].report_events = 0;
356      params.buckets[0].num_channels = 2;
357
358      params.buckets[0].channels[0].channel = 2412;
359      params.buckets[0].channels[1].channel = 2437;
360
361      params.buckets[1].bucket = 1;
362      params.buckets[1].band = WIFI_BAND_A;
363      params.buckets[1].period = 10000;               // 10 second
364      params.buckets[1].report_events = 1;
365      params.buckets[1].num_channels = 8;   // driver should ignore list since band is specified
366
367
368      params.buckets[1].channels[0].channel = 5180;
369      params.buckets[1].channels[1].channel = 5200;
370      params.buckets[1].channels[2].channel = 5220;
371      params.buckets[1].channels[3].channel = 5745;
372      params.buckets[1].channels[4].channel = 5765;
373      params.buckets[1].channels[5].channel = 5785;
374      params.buckets[1].channels[6].channel = 5805;
375      params.buckets[1].channels[7].channel = 5825;
376
377      params.buckets[2].bucket = 2;
378      params.buckets[2].band = WIFI_BAND_UNSPECIFIED;
379      params.buckets[2].period = 15000;                // 15 second
380      params.buckets[2].report_events = 2;
381      params.buckets[2].num_channels = 1;
382
383      params.buckets[2].channels[0].channel = 2462;
384
385    }
386
387    wifi_scan_result_handler handler;
388    memset(&handler, 0, sizeof(handler));
389    handler.on_scan_results_available = pfnOnResultsAvailable;
390    handler.on_scan_event = on_scan_event;
391
392    scanCmdId = getNewCmdId();
393    printMsg("Starting scan --->\n");
394    return wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS;
395}
396
397static void stopScan() {
398    wifi_request_id id = scanCmdId;
399    if (id == 0)
400        id = -1;
401
402    wifi_stop_gscan(id, wlan0Handle);
403    scanCmdId = 0;
404}
405
406wifi_scan_result *saved_scan_results;
407unsigned max_saved_scan_results;
408unsigned num_saved_scan_results;
409
410static void on_single_shot_scan_event(wifi_scan_event event, unsigned status) {
411    if (event == WIFI_SCAN_BUFFER_FULL) {
412        printMsg("Received scan complete event - WIFI_SCAN_BUFFER_FULL \n");
413    } else if(event == WIFI_SCAN_COMPLETE) {
414        printMsg("Received scan complete event  - WIFI_SCAN_COMPLETE\n");
415        putEventInCache(EVENT_TYPE_SCAN_COMPLETE, "One scan completed");
416    }
417}
418
419static void on_full_scan_result(wifi_request_id id, wifi_scan_result *r) {
420    if (num_saved_scan_results < max_saved_scan_results) {
421        wifi_scan_result *result = &(saved_scan_results[num_saved_scan_results]);
422        memcpy(result, r, sizeof(wifi_scan_result));
423        //printMsg("Retrieved full scan result for %s(%02x:%02x:%02x:%02x:%02x:%02x)\n",
424        //    result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], result->bssid[3],
425        //    result->bssid[4], result->bssid[5]);
426        num_saved_scan_results++;
427    }
428}
429
430static int scanOnce(wifi_band band, wifi_scan_result *results, int num_results) {
431
432    saved_scan_results = results;
433    max_saved_scan_results = num_results;
434    num_saved_scan_results = 0;
435
436    wifi_scan_cmd_params params;
437    memset(&params, 0, sizeof(params));
438
439    params.max_ap_per_scan = 10;
440    params.base_period = 5000;                        // 5 second by default
441    params.report_threshold = 90;
442    params.num_buckets = 1;
443
444    params.buckets[0].bucket = 0;
445    params.buckets[0].band = band;
446    params.buckets[0].period = 5000;                  // 5 second
447    params.buckets[0].report_events = 2;              // REPORT_EVENTS_AFTER_EACH_SCAN
448    params.buckets[0].num_channels = 0;
449
450    wifi_scan_result_handler handler;
451    memset(&handler, 0, sizeof(handler));
452    handler.on_scan_results_available = NULL;
453    handler.on_scan_event = on_single_shot_scan_event;
454    handler.on_full_scan_result = on_full_scan_result;
455
456    int scanCmdId = getNewCmdId();
457    printMsg("Starting scan --->\n");
458    if (wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS) {
459        int events = 0;
460        while (true) {
461            EventInfo info;
462            memset(&info, 0, sizeof(info));
463            getEventFromCache(info);
464            if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE
465                || info.type == EVENT_TYPE_SCAN_COMPLETE) {
466                int retrieved_num_results = num_saved_scan_results;
467                if (retrieved_num_results == 0) {
468                    printMsg("fetched 0 scan results, waiting for more..\n");
469                    continue;
470                } else {
471                    printMsg("fetched %d scan results\n", retrieved_num_results);
472
473                    /*
474                    printScanHeader();
475
476                    for (int i = 0; i < retrieved_num_results; i++) {
477                        printScanResult(results[i]);
478                    }
479                    */
480
481                    printMsg("Scan once completed, stopping scan\n");
482                    wifi_stop_gscan(scanCmdId, wlan0Handle);
483                    saved_scan_results = NULL;
484                    max_saved_scan_results = 0;
485                    num_saved_scan_results = 0;
486                    return retrieved_num_results;
487                }
488            }
489        }
490    } else {
491        return 0;
492    }
493}
494
495static void retrieveScanResults() {
496
497    wifi_scan_result results[256];
498    memset(results, 0, sizeof(wifi_scan_result) * 256);
499    printMsg("Retrieve Scan results available -->\n");
500    int num_results = 256;
501    int result = wifi_get_cached_gscan_results(wlan0Handle, 1, num_results, results, &num_results);
502    if (result < 0) {
503        printMsg("failed to fetch scan results : %d\n", result);
504        return;
505    } else {
506        printMsg("fetched %d scan results\n", num_results);
507    }
508
509    printScanHeader();
510    for (int i = 0; i < num_results; i++) {
511        printScanResult(results[i]);
512    }
513}
514
515
516static int compareScanResultsByRssi(const void *p1, const void *p2) {
517    const wifi_scan_result *result1 = static_cast<const wifi_scan_result *>(p1);
518    const wifi_scan_result *result2 = static_cast<const wifi_scan_result *>(p2);
519
520    /* RSSI is -ve, so lower one wins */
521    if (result1->rssi < result2->rssi) {
522        return 1;
523    } else if (result1->rssi == result2->rssi) {
524        return 0;
525    } else {
526        return -1;
527    }
528}
529
530static void sortScanResultsByRssi(wifi_scan_result *results, int num_results) {
531    qsort(results, num_results, sizeof(wifi_scan_result), &compareScanResultsByRssi);
532}
533
534static int removeDuplicateScanResults(wifi_scan_result *results, int num) {
535    /* remove duplicates by BSSID */
536    int num_results = num;
537    for (int i = 0; i < num_results; i++) {
538        //printMsg("Processing result[%d] - %02x:%02x:%02x:%02x:%02x:%02x\n", i,
539        //        results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
540        //        results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
541
542        for (int j = i + 1; j < num_results; ) {
543            if (memcmp(results[i].bssid, results[j].bssid, sizeof(mac_addr)) == 0) {
544                /* 'remove' this scan result from the list */
545                // printMsg("removing dupe entry\n");
546                int num_to_move = num_results - j - 1;
547                memmove(&results[j], &results[j+1], num_to_move * sizeof(wifi_scan_result));
548                num_results--;
549            } else {
550                j++;
551            }
552        }
553
554        // printMsg("num_results = %d\n", num_results);
555    }
556
557    return num_results;
558}
559
560static void onRTTResults (wifi_request_id id, unsigned num_results, wifi_rtt_result result[]) {
561
562    printMsg("RTT results!!\n");
563    printMsg("Addr\t\t\tts\t\tRSSI\tSpread\trtt\tsd\tspread\tdist\tsd\tspread\n");
564
565    for (unsigned i = 0; i < num_results; i++) {
566        printMsg("%02x:%02x:%02x:%02x:%02x:%02x\t%lld\t%d\t%d\t%lld\t%lld\t%lld\t%d\t%d\t%d\n",
567                result[i].addr[0], result[i].addr[1], result[i].addr[2], result[i].addr[3],
568                result[i].addr[4], result[i].addr[5], result[i].ts, result[i].rssi,
569                result[i].rssi_spread, result[i].rtt, result[i].rtt_sd, result[i].rtt_spread,
570                result[i].distance, result[i].distance_sd, result[i].distance_spread);
571    }
572
573    putEventInCache(EVENT_TYPE_RTT_RESULTS, "RTT results");
574}
575
576static void onHotlistAPFound(wifi_request_id id, unsigned num_results, wifi_scan_result *results) {
577
578    printMsg("Found hotlist APs\n");
579    for (unsigned i = 0; i < num_results; i++) {
580        printScanResult(results[i]);
581    }
582    putEventInCache(EVENT_TYPE_HOTLIST_AP_FOUND, "Found a hotlist AP");
583}
584
585static void onHotlistAPLost(wifi_request_id id, unsigned num_results, wifi_scan_result *results) {
586
587    printMsg("Lost hotlist APs\n");
588    for (unsigned i = 0; i < num_results; i++) {
589        printScanResult(results[i]);
590    }
591    putEventInCache(EVENT_TYPE_HOTLIST_AP_LOST, "Lost event Hotlist APs");
592}
593
594static void testRTT() {
595
596    wifi_scan_result results[256];
597    int num_results = scanOnce(WIFI_BAND_ABG, results, countof(results));
598    if (num_results == 0) {
599        printMsg("RTT aborted because of no scan results\n");
600        return;
601    } else {
602        printMsg("Retrieved %d scan results\n", num_results);
603    }
604
605    num_results = removeDuplicateScanResults(results, num_results);
606    /*
607    printMsg("Deduped scan results - %d\n", num_results);
608    for (int i = 0; i < num_results; i++) {
609        printScanResult(results[i]);
610    }
611    */
612
613    sortScanResultsByRssi(results, num_results);
614    printMsg("Sorted scan results -\n");
615    for (int i = 0; i < num_results; i++) {
616        printScanResult(results[i]);
617    }
618
619
620    static const int max_ap = 5;
621    wifi_rtt_config params[max_ap];
622    memset(params, 0, sizeof(params));
623
624    printMsg("Configuring RTT for %d APs, num_samples = %d\n",
625            min(num_results, max_ap), rtt_samples);
626
627    unsigned num_ap = 0;
628    for (int i = 0; i < min(num_results, max_ap); i++, num_ap++) {
629
630        memcpy(params[i].addr, results[i].bssid, sizeof(mac_addr));
631        mac_addr &addr = params[i].addr;
632        printMsg("Adding %02x:%02x:%02x:%02x:%02x:%02x (%d) for RTT\n", addr[0],
633                addr[1], addr[2], addr[3], addr[4], addr[5], results[i].channel);
634
635        params[i].type  = RTT_TYPE_1_SIDED;
636        params[i].channel.center_freq = results[i].channel;
637        params[i].channel.width = WIFI_CHAN_WIDTH_20;
638        params[i].peer  = WIFI_PEER_INVALID;
639        params[i].continuous = 1;
640        params[i].interval = 1000;
641        params[i].num_samples_per_measurement = rtt_samples;
642        params[i].num_retries_per_measurement = 10;
643    }
644
645    wifi_rtt_event_handler handler;
646    handler.on_rtt_results = &onRTTResults;
647
648    int result = wifi_rtt_range_request(rttCmdId, wlan0Handle, num_ap, params, handler);
649
650    if (result == WIFI_SUCCESS) {
651        printMsg("Waiting for RTT results\n");
652
653        while (true) {
654            EventInfo info;
655            memset(&info, 0, sizeof(info));
656            getEventFromCache(info);
657
658            if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE) {
659                retrieveScanResults();
660            } else if (info.type == EVENT_TYPE_RTT_RESULTS) {
661                break;
662            }
663        }
664    } else {
665        printMsg("Could not set setRTTAPs : %d\n", result);
666    }
667}
668
669
670static wifi_error setHotlistAPsUsingScanResult(wifi_bssid_hotlist_params *params){
671    printMsg("testHotlistAPs Scan started, waiting for event ...\n");
672    EventInfo info;
673    memset(&info, 0, sizeof(info));
674    getEventFromCache(info);
675
676    wifi_scan_result results[256];
677    memset(results, 0, sizeof(wifi_scan_result) * 256);
678
679    printMsg("Retrieving scan results for Hotlist AP setting\n");
680    int num_results = 256;
681    int result = wifi_get_cached_gscan_results(wlan0Handle, 1, num_results, results, &num_results);
682    if (result < 0) {
683        printMsg("failed to fetch scan results : %d\n", result);
684        return WIFI_ERROR_UNKNOWN;
685    } else {
686        printMsg("fetched %d scan results\n", num_results);
687    }
688
689    for (int i = 0; i < num_results; i++) {
690        printScanResult(results[i]);
691    }
692
693    for (int i = 0; i < stest_max_ap; i++) {
694        memcpy(params->ap[i].bssid, results[i].bssid, sizeof(mac_addr));
695        params->ap[i].low  = -htest_low_threshold;
696        params->ap[i].high = -htest_high_threshold;
697    }
698    params->num_ap = stest_max_ap;
699    return WIFI_SUCCESS;
700}
701
702static wifi_error setHotlistAPs() {
703    wifi_bssid_hotlist_params params;
704    memset(&params, 0, sizeof(params));
705
706    params.lost_ap_sample_size = HOTLIST_LOST_WINDOW;
707    if (num_hotlist_bssids > 0) {
708      for (int i = 0; i < num_hotlist_bssids; i++) {
709          memcpy(params.ap[i].bssid, hotlist_bssids[i], sizeof(mac_addr));
710          params.ap[i].low  = -htest_low_threshold;
711          params.ap[i].high = -htest_high_threshold;
712      }
713      params.num_ap = num_hotlist_bssids;
714    } else {
715      setHotlistAPsUsingScanResult(&params);
716    }
717
718    printMsg("BSSID\t\t\tHIGH\tLOW\n");
719    for (int i = 0; i < params.num_ap; i++) {
720        mac_addr &addr = params.ap[i].bssid;
721        printMsg("%02x:%02x:%02x:%02x:%02x:%02x\t%d\t%d\n", addr[0],
722                addr[1], addr[2], addr[3], addr[4], addr[5],
723                params.ap[i].high, params.ap[i].low);
724    }
725
726    wifi_hotlist_ap_found_handler handler;
727    handler.on_hotlist_ap_found = &onHotlistAPFound;
728    handler.on_hotlist_ap_lost = &onHotlistAPLost;
729    hotlistCmdId = getNewCmdId();
730    printMsg("Setting hotlist APs threshold\n");
731    return wifi_set_bssid_hotlist(hotlistCmdId, wlan0Handle, params, handler);
732}
733
734static void resetHotlistAPs() {
735    printMsg(", stoping Hotlist AP scanning\n");
736    wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
737}
738
739static void setPnoMacOui() {
740    wifi_set_scanning_mac_oui(wlan0Handle, mac_oui);
741}
742
743static void testHotlistAPs(){
744
745    EventInfo info;
746    memset(&info, 0, sizeof(info));
747
748    printMsg("starting Hotlist AP scanning\n");
749    if (!startScan(&onScanResultsAvailable, stest_max_ap,stest_base_period, stest_threshold)) {
750        printMsg("testHotlistAPs failed to start scan!!\n");
751        return;
752    }
753
754    int result = setHotlistAPs();
755    if (result == WIFI_SUCCESS) {
756        printMsg("Waiting for Hotlist AP event\n");
757        while (true) {
758            memset(&info, 0, sizeof(info));
759            getEventFromCache(info);
760
761            if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE) {
762                retrieveScanResults();
763            } else if (info.type == EVENT_TYPE_HOTLIST_AP_FOUND ||
764                   info.type == EVENT_TYPE_HOTLIST_AP_LOST) {
765                printMsg("Hotlist APs");
766                if (--max_event_wait > 0)
767                  printMsg(", waiting for more event ::%d\n", max_event_wait);
768                else
769                  break;
770            }
771        }
772        resetHotlistAPs();
773    } else {
774        printMsg("Could not set AP hotlist : %d\n", result);
775    }
776}
777
778static void onSignificantWifiChange(wifi_request_id id,
779        unsigned num_results, wifi_significant_change_result **results)
780{
781    printMsg("Significant wifi change for %d\n", num_results);
782    for (unsigned i = 0; i < num_results; i++) {
783        printSignificantChangeResult(results[i]);
784    }
785    putEventInCache(EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE, "significant wifi change noticed");
786}
787
788static int SelectSignificantAPsFromScanResults() {
789    wifi_scan_result results[256];
790    memset(results, 0, sizeof(wifi_scan_result) * 256);
791    printMsg("Retrieving scan results for significant wifi change setting\n");
792    int num_results = 256;
793    int result = wifi_get_cached_gscan_results(wlan0Handle, 1, num_results, results, &num_results);
794    if (result < 0) {
795        printMsg("failed to fetch scan results : %d\n", result);
796        return WIFI_ERROR_UNKNOWN;
797    } else {
798        printMsg("fetched %d scan results\n", num_results);
799    }
800
801    for (int i = 0; i < num_results; i++) {
802        printScanResult(results[i]);
803    }
804
805    wifi_significant_change_params params;
806    memset(&params, 0, sizeof(params));
807
808    params.rssi_sample_size = swctest_rssi_sample_size;
809    params.lost_ap_sample_size = swctest_rssi_lost_ap;
810    params.min_breaching = swctest_rssi_min_breaching;
811
812    for (int i = 0; i < stest_max_ap; i++) {
813        memcpy(params.ap[i].bssid, results[i].bssid, sizeof(mac_addr));
814        params.ap[i].low  = results[i].rssi - swctest_rssi_ch_threshold;
815        params.ap[i].high = results[i].rssi + swctest_rssi_ch_threshold;
816    }
817    params.num_ap = stest_max_ap;
818
819    printMsg("Settting Significant change params rssi_sample_size#%d lost_ap_sample_size#%d"
820        " and min_breaching#%d\n", params.rssi_sample_size,
821        params.lost_ap_sample_size , params.min_breaching);
822    printMsg("BSSID\t\t\tHIGH\tLOW\n");
823    for (int i = 0; i < params.num_ap; i++) {
824        mac_addr &addr = params.ap[i].bssid;
825        printMsg("%02x:%02x:%02x:%02x:%02x:%02x\t%d\t%d\n", addr[0],
826                addr[1], addr[2], addr[3], addr[4], addr[5],
827                params.ap[i].high, params.ap[i].low);
828    }
829    wifi_significant_change_handler handler;
830    memset(&handler, 0, sizeof(handler));
831    handler.on_significant_change = &onSignificantWifiChange;
832
833    int id = getNewCmdId();
834    return wifi_set_significant_change_handler(id, wlan0Handle, params, handler);
835
836}
837
838static void untrackSignificantChange() {
839    printMsg(", Stop tracking SignificantChange\n");
840    wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
841}
842
843static void trackSignificantChange() {
844    printMsg("starting trackSignificantChange\n");
845
846    if (!startScan(&onScanResultsAvailable, stest_max_ap,stest_base_period, stest_threshold)) {
847        printMsg("trackSignificantChange failed to start scan!!\n");
848        return;
849    } else {
850        printMsg("trackSignificantChange Scan started, waiting for event ...\n");
851    }
852
853    EventInfo info;
854    memset(&info, 0, sizeof(info));
855    getEventFromCache(info);
856
857    int result = SelectSignificantAPsFromScanResults();
858    if (result == WIFI_SUCCESS) {
859        printMsg("Waiting for significant wifi change event\n");
860        while (true) {
861            memset(&info, 0, sizeof(info));
862            getEventFromCache(info);
863
864            if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE) {
865                retrieveScanResults();
866            } else if(info.type == EVENT_TYPE_SIGNIFICANT_WIFI_CHANGE) {
867                printMsg("Received significant wifi change");
868                if (--max_event_wait > 0)
869                    printMsg(", waiting for more event ::%d\n", max_event_wait);
870                else
871                    break;
872            }
873        }
874        untrackSignificantChange();
875    } else {
876        printMsg("Failed to set significant change  ::%d\n", result);
877    }
878}
879
880/* -------------------------------------------  */
881/* tests                                        */
882/* -------------------------------------------  */
883
884void testScan() {
885    printf("starting scan with max_ap_per_scan#%d  base_period#%d  threshold#%d \n",
886           stest_max_ap,stest_base_period, stest_threshold);
887    if (!startScan(&onScanResultsAvailable, stest_max_ap,stest_base_period, stest_threshold)) {
888        printMsg("failed to start scan!!\n");
889        return;
890    } else {
891        EventInfo info;
892        memset(&info, 0, sizeof(info));
893
894        while (true) {
895            getEventFromCache(info);
896            printMsg("retrieved event %d : %s\n", info.type, info.buf);
897            retrieveScanResults();
898            if(--max_event_wait > 0)
899              printMsg("Waiting for more :: %d event \n", max_event_wait);
900            else
901              break;
902        }
903
904        stopScan();
905        printMsg("stopped scan\n");
906    }
907}
908
909void testStopScan() {
910    stopScan();
911    printMsg("stopped scan\n");
912}
913
914byte parseHexChar(char ch) {
915    if (isdigit(ch))
916        return ch - '0';
917    else if ('A' <= ch && ch <= 'F')
918        return ch - 'A' + 10;
919    else if ('a' <= ch && ch <= 'f')
920        return ch - 'a' + 10;
921    else {
922        printMsg("invalid character in bssid %c\n", ch);
923        return 0;
924    }
925}
926
927byte parseHexByte(char ch1, char ch2) {
928    return (parseHexChar(ch1) << 4) | parseHexChar(ch2);
929}
930
931void parseMacAddress(const char *str, mac_addr addr) {
932    addr[0] = parseHexByte(str[0], str[1]);
933    addr[1] = parseHexByte(str[3], str[4]);
934    addr[2] = parseHexByte(str[6], str[7]);
935    addr[3] = parseHexByte(str[9], str[10]);
936    addr[4] = parseHexByte(str[12], str[13]);
937    addr[5] = parseHexByte(str[15], str[16]);
938    // printMsg("read mac addr: %02x:%02x:%02x:%02x:%02x:%02x\n", addr[0],
939    //      addr[1], addr[2], addr[3], addr[4], addr[5]);
940}
941
942void parseMacOUI(char *str, unsigned char *addr) {
943    addr[0] = parseHexByte(str[0], str[1]);
944    addr[1] = parseHexByte(str[3], str[4]);
945    addr[2] = parseHexByte(str[6], str[7]);
946    printMsg("read mac OUI: %02x:%02x:%02x\n", addr[0],
947            addr[1], addr[2]);
948}
949
950void readTestOptions(int argc, char *argv[]){
951
952    printf("Total number of argc #%d\n", argc);
953    for (int j = 1; j < argc-1; j++) {
954        if (strcmp(argv[j], "-max_ap") == 0 && isdigit(argv[j+1][0])) {
955            stest_max_ap = atoi(argv[++j]);
956            printf(" max_ap #%d\n", stest_max_ap);
957        } else if (strcmp(argv[j], "-base_period") == 0 && isdigit(argv[j+1][0])) {
958            stest_base_period = atoi(argv[++j]);
959            printf(" base_period #%d\n", stest_base_period);
960        } else if (strcmp(argv[j], "-threshold") == 0 && isdigit(argv[j+1][0])) {
961            stest_threshold = atoi(argv[++j]);
962            printf(" threshold #%d\n", stest_threshold);
963        } else if (strcmp(argv[j], "-avg_RSSI") == 0 && isdigit(argv[j+1][0])) {
964            swctest_rssi_sample_size = atoi(argv[++j]);
965            printf(" avg_RSSI #%d\n", swctest_rssi_sample_size);
966        } else if (strcmp(argv[j], "-ap_loss") == 0 && isdigit(argv[j+1][0])) {
967            swctest_rssi_lost_ap = atoi(argv[++j]);
968            printf(" ap_loss #%d\n", swctest_rssi_lost_ap);
969        } else if (strcmp(argv[j], "-ap_breach") == 0 && isdigit(argv[j+1][0])) {
970            swctest_rssi_min_breaching = atoi(argv[++j]);
971            printf(" ap_breach #%d\n", swctest_rssi_min_breaching);
972        } else if (strcmp(argv[j], "-ch_threshold") == 0 && isdigit(argv[j+1][0])) {
973            swctest_rssi_ch_threshold = atoi(argv[++j]);
974            printf(" ch_threshold #%d\n", swctest_rssi_ch_threshold);
975        } else if (strcmp(argv[j], "-wt_event") == 0 && isdigit(argv[j+1][0])) {
976            max_event_wait = atoi(argv[++j]);
977            printf(" wt_event #%d\n", max_event_wait);
978        } else if (strcmp(argv[j], "-low_th") == 0 && isdigit(argv[j+1][0])) {
979            htest_low_threshold = atoi(argv[++j]);
980            printf(" low_threshold #-%d\n", htest_low_threshold);
981        } else if (strcmp(argv[j], "-high_th") == 0 && isdigit(argv[j+1][0])) {
982            htest_high_threshold = atoi(argv[++j]);
983            printf(" high_threshold #-%d\n", htest_high_threshold);
984        } else if (strcmp(argv[j], "-hotlist_bssids") == 0 && isxdigit(argv[j+1][0])) {
985            j++;
986            for (num_hotlist_bssids = 0;
987                        j < argc && isxdigit(argv[j][0]);
988                        j++, num_hotlist_bssids++) {
989                parseMacAddress(argv[j], hotlist_bssids[num_hotlist_bssids]);
990            }
991            j -= 1;
992        } else if (strcmp(argv[j], "-channel_list") == 0 && isxdigit(argv[j+1][0])) {
993            j++;
994            for (num_channels = 0; j < argc && isxdigit(argv[j][0]); j++, num_channels++) {
995                channel_list[num_channels] = atoi(argv[j]);
996            }
997            j -= 1;
998        } else if ((strcmp(argv[j], "-get_ch_list") == 0)) {
999            if(strcmp(argv[j + 1], "a") == 0) {
1000                band = WIFI_BAND_A_WITH_DFS;
1001            } else if(strcmp(argv[j + 1], "bg") == 0) {
1002                band = WIFI_BAND_BG;
1003            } else if(strcmp(argv[j + 1], "abg") == 0) {
1004                band = WIFI_BAND_ABG_WITH_DFS;
1005            } else if(strcmp(argv[j + 1], "a_nodfs") == 0) {
1006                band = WIFI_BAND_A;
1007            } else if(strcmp(argv[j + 1], "dfs") == 0) {
1008                band = WIFI_BAND_A_DFS;
1009            } else if(strcmp(argv[j + 1], "abg_nodfs") == 0) {
1010                band = WIFI_BAND_ABG;
1011            }
1012            j++;
1013        } else if ((strcmp(argv[j], "-rtt_samples") == 0)) {
1014            rtt_samples = atoi(argv[++j]);
1015            printf(" rtt_retries #-%d\n", rtt_samples);
1016        } else if (strcmp(argv[j], "-scan_mac_oui") == 0 && isxdigit(argv[j+1][0])) {
1017            parseMacOUI(argv[++j], mac_oui);
1018     }
1019    }
1020}
1021
1022wifi_iface_stat link_stat;
1023wifi_radio_stat trx_stat;
1024wifi_peer_info peer_info;
1025wifi_rate_stat rate_stat[32];
1026void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat,
1027         int num_radios, wifi_radio_stat *radio_stat)
1028{
1029    int num_peer = iface_stat->num_peers;
1030    memcpy(&trx_stat, radio_stat, sizeof(wifi_radio_stat));
1031    memcpy(&link_stat, iface_stat, sizeof(wifi_iface_stat));
1032    memcpy(&peer_info, iface_stat->peer_info, num_peer*sizeof(wifi_peer_info));
1033    int num_rate = peer_info.num_rate;
1034    memcpy(&rate_stat, iface_stat->peer_info->rate_stats, num_rate*sizeof(wifi_rate_stat));
1035}
1036
1037void printFeatureListBitMask(void)
1038{
1039    printMsg("WIFI_FEATURE_INFRA              0x0001      - Basic infrastructure mode\n");
1040    printMsg("WIFI_FEATURE_INFRA_5G           0x0002      - Support for 5 GHz Band\n");
1041    printMsg("WIFI_FEATURE_HOTSPOT            0x0004      - Support for GAS/ANQP\n");
1042    printMsg("WIFI_FEATURE_P2P                0x0008      - Wifi-Direct\n");
1043    printMsg("WIFI_FEATURE_SOFT_AP            0x0010      - Soft AP\n");
1044    printMsg("WIFI_FEATURE_GSCAN              0x0020      - Google-Scan APIs\n");
1045    printMsg("WIFI_FEATURE_NAN                0x0040      - Neighbor Awareness Networking\n");
1046    printMsg("WIFI_FEATURE_D2D_RTT            0x0080      - Device-to-device RTT\n");
1047    printMsg("WIFI_FEATURE_D2AP_RTT           0x0100      - Device-to-AP RTT\n");
1048    printMsg("WIFI_FEATURE_BATCH_SCAN         0x0200      - Batched Scan (legacy)\n");
1049    printMsg("WIFI_FEATURE_PNO                0x0400      - Preferred network offload\n");
1050    printMsg("WIFI_FEATURE_ADDITIONAL_STA     0x0800      - Support for two STAs\n");
1051    printMsg("WIFI_FEATURE_TDLS               0x1000      - Tunnel directed link setup\n");
1052    printMsg("WIFI_FEATURE_TDLS_OFFCHANNEL    0x2000      - Support for TDLS off channel\n");
1053    printMsg("WIFI_FEATURE_EPR                0x4000      - Enhanced power reporting\n");
1054    printMsg("WIFI_FEATURE_AP_STA             0x8000      - Support for AP STA Concurrency\n");
1055}
1056
1057char *rates[] = {
1058    "1Mbps",
1059    "2Mbps",
1060	"5.5Mbps",
1061	"6Mbps",
1062	"9Mbps",
1063	"11Mbps",
1064	"12Mbps",
1065	"18Mbps",
1066	"24Mbps",
1067	"36Mbps",
1068	"48Mbps",
1069	"54Mbps",
1070	"VHT MCS0 ss1",
1071	"VHT MCS1 ss1",
1072	"VHT MCS2 ss1",
1073	"VHT MCS3 ss1",
1074	"VHT MCS4 ss1",
1075	"VHT MCS5 ss1",
1076	"VHT MCS6 ss1",
1077	"VHT MCS7 ss1",
1078    "VHT MCS8 ss1",
1079	"VHT MCS9 ss1",
1080	"VHT MCS0 ss2",
1081	"VHT MCS1 ss2",
1082	"VHT MCS2 ss2",
1083	"VHT MCS3 ss2",
1084	"VHT MCS4 ss2",
1085	"VHT MCS5 ss2",
1086	"VHT MCS6 ss2",
1087	"VHT MCS7 ss2",
1088	"VHT MCS8 ss2",
1089	"VHT MCS9 ss2"
1090	};
1091
1092void printLinkStats(wifi_iface_stat link_stat, wifi_radio_stat trx_stat)
1093{
1094    printMsg("Printing link layer statistics:\n");
1095    printMsg("-------------------------------\n");
1096    printMsg("beacon_rx = %d\n", link_stat.beacon_rx);
1097    printMsg("RSSI = %d\n", link_stat.rssi_mgmt);
1098    printMsg("AC_BE:\n");
1099    printMsg("txmpdu = %d\n", link_stat.ac[WIFI_AC_BE].tx_mpdu);
1100    printMsg("rxmpdu = %d\n", link_stat.ac[WIFI_AC_BE].rx_mpdu);
1101    printMsg("mpdu_lost = %d\n", link_stat.ac[WIFI_AC_BE].mpdu_lost);
1102    printMsg("retries = %d\n", link_stat.ac[WIFI_AC_BE].retries);
1103    printMsg("AC_BK:\n");
1104    printMsg("txmpdu = %d\n", link_stat.ac[WIFI_AC_BK].tx_mpdu);
1105    printMsg("rxmpdu = %d\n", link_stat.ac[WIFI_AC_BK].rx_mpdu);
1106    printMsg("mpdu_lost = %d\n", link_stat.ac[WIFI_AC_BK].mpdu_lost);
1107    printMsg("AC_VI:\n");
1108    printMsg("txmpdu = %d\n", link_stat.ac[WIFI_AC_VI].tx_mpdu);
1109    printMsg("rxmpdu = %d\n", link_stat.ac[WIFI_AC_VI].rx_mpdu);
1110    printMsg("mpdu_lost = %d\n", link_stat.ac[WIFI_AC_VI].mpdu_lost);
1111    printMsg("AC_VO:\n");
1112    printMsg("txmpdu = %d\n", link_stat.ac[WIFI_AC_VO].tx_mpdu);
1113    printMsg("rxmpdu = %d\n", link_stat.ac[WIFI_AC_VO].rx_mpdu);
1114    printMsg("mpdu_lost = %d\n", link_stat.ac[WIFI_AC_VO].mpdu_lost);
1115    printMsg("\n");
1116    printMsg("Printing radio statistics:\n");
1117    printMsg("--------------------------\n");
1118    printMsg("on time = %d\n", trx_stat.on_time);
1119    printMsg("tx time = %d\n", trx_stat.tx_time);
1120    printMsg("rx time = %d\n", trx_stat.rx_time);
1121    printMsg("\n");
1122    printMsg("Printing rate statistics:\n");
1123    printMsg("-------------------------\n");
1124    printMsg("%27s %12s %14s %15s\n", "TX",  "RX", "LOST", "RETRIES");
1125    for (int i=0; i < 32; i++) {
1126        printMsg("%-15s  %10d   %10d    %10d    %10d\n",
1127	    rates[i], rate_stat[i].tx_mpdu, rate_stat[i].rx_mpdu,
1128	    rate_stat[i].mpdu_lost, rate_stat[i].retries);
1129    }
1130}
1131
1132void getLinkStats(void)
1133{
1134    wifi_stats_result_handler handler;
1135    memset(&handler, 0, sizeof(handler));
1136    handler.on_link_stats_results = &onLinkStatsResults;
1137
1138    int result = wifi_get_link_stats(0, wlan0Handle, handler);
1139    if (result < 0) {
1140        printMsg("failed to get link statistics - %d\n", result);
1141    } else {
1142        printLinkStats(link_stat, trx_stat);
1143    }
1144}
1145
1146void getChannelList(void)
1147{
1148    wifi_channel channel[MAX_CH_BUF_SIZE];
1149    int num_channels = 0, i;
1150
1151    int result = wifi_get_valid_channels(wlan0Handle, band, MAX_CH_BUF_SIZE,
1152                     channel, &num_channels);
1153    printMsg("Number of channels - %d\nChannel List:\n",num_channels);
1154    for (i = 0; i < num_channels; i++) {
1155        printMsg("%d MHz\n", channel[i]);
1156    }
1157}
1158
1159void getFeatureSet(void)
1160{
1161    feature_set set;
1162    int result = wifi_get_supported_feature_set(wlan0Handle, &set);
1163
1164    if (result < 0) {
1165        printMsg("Error %d\n",result);
1166        return;
1167    }
1168    printFeatureListBitMask();
1169    printMsg("Supported feature set bit mask - %x\n", set);
1170    return;
1171}
1172
1173void getFeatureSetMatrix(void)
1174{
1175    feature_set set[MAX_FEATURE_SET];
1176    int size;
1177
1178    int result = wifi_get_concurrency_matrix(wlan0Handle, MAX_FEATURE_SET, set, &size);
1179
1180    if (result < 0) {
1181        printMsg("Error %d\n",result);
1182        return;
1183    }
1184    printFeatureListBitMask();
1185    for (int i = 0; i < size; i++)
1186        printMsg("Concurrent feature set - %x\n", set[i]);
1187    return;
1188}
1189
1190
1191
1192int main(int argc, char *argv[]) {
1193
1194    pthread_mutex_init(&printMutex, NULL);
1195
1196    if (init() != 0) {
1197        printMsg("could not initiate HAL");
1198        return -1;
1199    } else {
1200        printMsg("successfully initialized HAL; wlan0 = %p\n", wlan0Handle);
1201    }
1202
1203    pthread_cond_init(&eventCacheCondition, NULL);
1204    pthread_mutex_init(&eventCacheMutex, NULL);
1205
1206    pthread_t tidEvent;
1207    pthread_create(&tidEvent, NULL, &eventThreadFunc, NULL);
1208
1209    sleep(2);     // let the thread start
1210
1211    if (argc < 2 || argv[1][0] != '-') {
1212        printf("Usage:  halutil [OPTION]\n");
1213        printf(" -s               start AP scan test\n");
1214        printf(" -swc             start Significant Wifi change test\n");
1215        printf(" -h               start Hotlist APs scan test\n");
1216        printf(" -ss              stop scan test\n");
1217        printf(" -max_ap          Max AP for scan \n");
1218        printf(" -base_period     Base period for scan \n");
1219        printf(" -threshold       Threshold scan test\n");
1220        printf(" -avg_RSSI        samples for averaging RSSI\n");
1221        printf(" -ap_loss         samples to confirm AP loss\n");
1222        printf(" -ap_breach       APs breaching threshold\n");
1223        printf(" -ch_threshold    Change in threshold\n");
1224        printf(" -wt_event        Waiting event for test\n");
1225        printf(" -low_th          Low threshold for hotlist APs\n");
1226        printf(" -hight_th        High threshold for hotlist APs\n");
1227        printf(" -hotlist_bssids  BSSIDs for hotlist test\n");
1228        printf(" -stats       print link layer statistics\n");
1229        printf(" -get_ch_list <a/bg/abg/a_nodfs/abg_nodfs/dfs>  Get channel list\n");
1230        printf(" -get_feature_set  Get Feature set\n");
1231        printf(" -get_feature_matrix  Get concurrent feature matrix\n");
1232        printf(" -rtt             Run RTT on nearby APs\n");
1233        printf(" -rtt_samples     Run RTT on nearby APs\n");
1234        printf(" -scan_mac_oui XY:AB:CD\n");
1235        printf(" -nodfs <0|1>     Turn OFF/ON non-DFS locales\n");
1236        goto cleanup;
1237    }
1238    memset(mac_oui, 0, 3);
1239
1240    if (strcmp(argv[1], "-s") == 0) {
1241        readTestOptions(argc, argv);
1242        setPnoMacOui();
1243        testScan();
1244    }else if(strcmp(argv[1], "-swc") == 0){
1245        readTestOptions(argc, argv);
1246        setPnoMacOui();
1247        trackSignificantChange();
1248    }else if (strcmp(argv[1], "-ss") == 0) {
1249        // Stop scan so clear the OUI too
1250        setPnoMacOui();
1251        testStopScan();
1252    }else if ((strcmp(argv[1], "-h") == 0)  ||
1253              (strcmp(argv[1], "-hotlist_bssids") == 0)) {
1254        readTestOptions(argc, argv);
1255        setPnoMacOui();
1256        testHotlistAPs();
1257    }else if (strcmp(argv[1], "-stats") == 0) {
1258        getLinkStats();
1259    } else if ((strcmp(argv[1], "-rtt") == 0)) {
1260        readTestOptions(argc, argv);
1261        testRTT();
1262    } else if ((strcmp(argv[1], "-get_ch_list") == 0)) {
1263        readTestOptions(argc, argv);
1264        getChannelList();
1265    } else if ((strcmp(argv[1], "-get_feature_set") == 0)) {
1266        getFeatureSet();
1267    } else if ((strcmp(argv[1], "-get_feature_matrix") == 0)) {
1268        getFeatureSetMatrix();
1269    } else if ((strcmp(argv[1], "-scan_mac_oui") == 0)) {
1270        readTestOptions(argc, argv);
1271        setPnoMacOui();
1272        testScan();
1273    } else if (strcmp(argv[1], "-nodfs") == 0) {
1274        u32 nodfs = 0;
1275        if (argc > 2)
1276            nodfs = (u32)atoi(argv[2]);
1277        wifi_set_nodfs_flag(wlan0Handle, nodfs);
1278    }
1279cleanup:
1280    cleanup();
1281    return 0;
1282}
1283