Home | History | Annotate | Download | only in halutil
      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 
     15 pthread_mutex_t printMutex;
     16 void 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 
     27 template<typename T, unsigned N>
     28 unsigned countof(T (&rgt)[N]) {
     29     return N;
     30 }
     31 
     32 template<typename T>
     33 T 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 
     42 static wifi_handle halHandle;
     43 static wifi_interface_handle *ifaceHandles;
     44 static wifi_interface_handle wlan0Handle;
     45 static wifi_interface_handle p2p0Handle;
     46 static int numIfaceHandles;
     47 static int cmdId = 0;
     48 static int ioctl_sock = 0;
     49 static int max_event_wait = 5;
     50 static int stest_max_ap = 10;
     51 static int stest_base_period = 5000;
     52 static int stest_threshold = 80;
     53 static int swctest_rssi_sample_size =  3;
     54 static int swctest_rssi_lost_ap =  3;
     55 static int swctest_rssi_min_breaching =  2;
     56 static int swctest_rssi_ch_threshold =  1;
     57 static int htest_low_threshold =  90;
     58 static int htest_high_threshold =  10;
     59 static int rtt_samples = 30;
     60 static wifi_band band = WIFI_BAND_UNSPECIFIED;
     61 
     62 mac_addr hotlist_bssids[16];
     63 unsigned char mac_oui[3];
     64 int channel_list[16];
     65 int num_hotlist_bssids = 0;
     66 int num_channels = 0;
     67 
     68 void parseMacAddress(const char *str, mac_addr addr);
     69 
     70 int 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 
    120 static 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 
    161 static void cleaned_up_handler(wifi_handle handle) {
    162     printMsg("HAL cleaned up handler\n");
    163     halHandle = NULL;
    164     ifaceHandles = NULL;
    165 }
    166 
    167 static void cleanup() {
    168     printMsg("cleaning up HAL\n");
    169     wifi_cleanup(halHandle, cleaned_up_handler);
    170 }
    171 
    172 static 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 
    182 static int getNewCmdId() {
    183     return cmdId++;
    184 }
    185 
    186 /* -------------------------------------------  */
    187 /* helpers                                      */
    188 /* -------------------------------------------  */
    189 
    190 void printScanHeader() {
    191     printMsg("SSID\t\t\t\t\tBSSID\t\t  RSSI\tchannel\ttimestamp\tRTT\tRTT SD\n");
    192 }
    193 
    194 void 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 
    208 void 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 
    222 void 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 
    239 typedef 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 
    248 typedef struct {
    249     int type;
    250     char buf[256];
    251 } EventInfo;
    252 
    253 const int MAX_EVENTS_IN_CACHE = 256;
    254 EventInfo eventCache[256];
    255 int eventsInCache = 0;
    256 pthread_cond_t eventCacheCondition;
    257 pthread_mutex_t eventCacheMutex;
    258 
    259 void 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 
    273 void 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 
    291 int numScanResultsAvailable = 0;
    292 static 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 
    298 static 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 
    306 static int scanCmdId;
    307 static int hotlistCmdId;
    308 static int significantChangeCmdId;
    309 static int rttCmdId;
    310 
    311 static 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 
    397 static 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 
    406 wifi_scan_result *saved_scan_results;
    407 unsigned max_saved_scan_results;
    408 unsigned num_saved_scan_results;
    409 
    410 static 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 
    419 static 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 
    430 static 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 
    495 static 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 
    516 static 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 
    530 static void sortScanResultsByRssi(wifi_scan_result *results, int num_results) {
    531     qsort(results, num_results, sizeof(wifi_scan_result), &compareScanResultsByRssi);
    532 }
    533 
    534 static 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 
    560 static 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 
    576 static 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 
    585 static 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 
    594 static 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 
    670 static 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 
    702 static 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 
    734 static void resetHotlistAPs() {
    735     printMsg(", stoping Hotlist AP scanning\n");
    736     wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
    737 }
    738 
    739 static void setPnoMacOui() {
    740     wifi_set_scanning_mac_oui(wlan0Handle, mac_oui);
    741 }
    742 
    743 static 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 
    778 static 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 
    788 static 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 
    838 static void untrackSignificantChange() {
    839     printMsg(", Stop tracking SignificantChange\n");
    840     wifi_reset_bssid_hotlist(hotlistCmdId, wlan0Handle);
    841 }
    842 
    843 static 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 
    884 void 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 
    909 void testStopScan() {
    910     stopScan();
    911     printMsg("stopped scan\n");
    912 }
    913 
    914 byte 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 
    927 byte parseHexByte(char ch1, char ch2) {
    928     return (parseHexChar(ch1) << 4) | parseHexChar(ch2);
    929 }
    930 
    931 void 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 
    942 void 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 
    950 void 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 
   1022 wifi_iface_stat link_stat;
   1023 wifi_radio_stat trx_stat;
   1024 wifi_peer_info peer_info;
   1025 wifi_rate_stat rate_stat[32];
   1026 void 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 
   1037 void 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 
   1057 char *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 
   1092 void 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 
   1132 void 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 
   1146 void 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 
   1159 void 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 
   1173 void 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 
   1192 int 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     }
   1279 cleanup:
   1280     cleanup();
   1281     return 0;
   1282 }
   1283