Home | History | Annotate | Download | only in wifi_hal
      1 #include <stdint.h>
      2 #include <fcntl.h>
      3 #include <sys/socket.h>
      4 #include <netlink/genl/genl.h>
      5 #include <netlink/genl/family.h>
      6 #include <netlink/genl/ctrl.h>
      7 #include <linux/rtnetlink.h>
      8 #include <netpacket/packet.h>
      9 #include <linux/filter.h>
     10 #include <linux/errqueue.h>
     11 
     12 #include <linux/pkt_sched.h>
     13 #include <netlink/object-api.h>
     14 #include <netlink/netlink.h>
     15 #include <netlink/socket.h>
     16 #include <netlink-types.h>
     17 
     18 #include "nl80211_copy.h"
     19 
     20 #include "sync.h"
     21 
     22 #define LOG_TAG  "WifiHAL"
     23 
     24 #include <utils/Log.h>
     25 #include <utils/String8.h>
     26 
     27 #include "wifi_hal.h"
     28 #include "common.h"
     29 #include "cpp_bindings.h"
     30 
     31 using namespace android;
     32 #define RTT_RESULT_SIZE (sizeof(wifi_rtt_result));
     33 typedef enum {
     34 
     35     RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
     36     RTT_SUBCMD_CANCEL_CONFIG,
     37     RTT_SUBCMD_GETCAPABILITY,
     38 } RTT_SUB_COMMAND;
     39 
     40 typedef enum {
     41     RTT_ATTRIBUTE_TARGET_CNT = 0,
     42     RTT_ATTRIBUTE_TARGET_INFO,
     43     RTT_ATTRIBUTE_TARGET_MAC,
     44     RTT_ATTRIBUTE_TARGET_TYPE,
     45     RTT_ATTRIBUTE_TARGET_PEER,
     46     RTT_ATTRIBUTE_TARGET_CHAN,
     47     RTT_ATTRIBUTE_TARGET_PERIOD,
     48     RTT_ATTRIBUTE_TARGET_NUM_BURST,
     49     RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
     50     RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
     51     RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
     52     RTT_ATTRIBUTE_TARGET_LCI,
     53     RTT_ATTRIBUTE_TARGET_LCR,
     54     RTT_ATTRIBUTE_TARGET_BURST_DURATION,
     55     RTT_ATTRIBUTE_TARGET_PREAMBLE,
     56     RTT_ATTRIBUTE_TARGET_BW,
     57     RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
     58     RTT_ATTRIBUTE_RESULTS_PER_TARGET,
     59     RTT_ATTRIBUTE_RESULT_CNT,
     60     RTT_ATTRIBUTE_RESULT
     61 } RTT_ATTRIBUTE;
     62 typedef struct strmap_entry {
     63     int			id;
     64     String8		text;
     65 } strmap_entry_t;
     66 struct dot11_rm_ie {
     67     u8 id;
     68     u8 len;
     69     u8 token;
     70     u8 mode;
     71     u8 type;
     72 } __attribute__ ((packed));
     73 typedef struct dot11_rm_ie dot11_rm_ie_t;
     74 #define DOT11_HDR_LEN 2
     75 #define DOT11_RM_IE_LEN       5
     76 #define DOT11_MNG_MEASURE_REQUEST_ID		38	/* 11H MeasurementRequest */
     77 #define DOT11_MEASURE_TYPE_LCI		8   /* d11 measurement LCI type */
     78 #define DOT11_MEASURE_TYPE_CIVICLOC	11  /* d11 measurement location civic */
     79 
     80 static const strmap_entry_t err_info[] = {
     81     {RTT_STATUS_SUCCESS, String8("Success")},
     82     {RTT_STATUS_FAILURE, String8("Failure")},
     83     {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")},
     84     {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")},
     85     {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")},
     86     {RTT_STATUS_FAIL_REJECTED, String8("Rejected")},
     87     {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")},
     88     {RTT_STATUS_FAIL_SCHEDULE,  String8("schedule failed")},
     89     {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")},
     90     {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")},
     91     {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")},
     92     {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")},
     93     {RTT_STATUS_ABORTED, String8("aborted")}
     94 };
     95 
     96     static const char*
     97 get_err_info(int status)
     98 {
     99     int i;
    100     const strmap_entry_t *p_entry;
    101     int num_entries = sizeof(err_info)/ sizeof(err_info[0]);
    102     /* scan thru the table till end */
    103     p_entry = err_info;
    104     for (i = 0; i < (int) num_entries; i++)
    105     {
    106         if (p_entry->id == status)
    107             return p_entry->text;
    108         p_entry++;		/* next entry */
    109     }
    110     return "unknown error";			/* not found */
    111 }
    112 
    113 class GetRttCapabilitiesCommand : public WifiCommand
    114 {
    115     wifi_rtt_capabilities *mCapabilities;
    116 public:
    117     GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
    118         : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
    119     {
    120         memset(mCapabilities, 0, sizeof(*mCapabilities));
    121     }
    122 
    123     virtual int create() {
    124         ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
    125 
    126         int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
    127         if (ret < 0) {
    128             return ret;
    129         }
    130 
    131         return ret;
    132     }
    133 
    134 protected:
    135     virtual int handleResponse(WifiEvent& reply) {
    136 
    137         ALOGD("In GetRttCapabilitiesCommand::handleResponse");
    138 
    139         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    140             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    141             return NL_SKIP;
    142         }
    143 
    144         int id = reply.get_vendor_id();
    145         int subcmd = reply.get_vendor_subcmd();
    146 
    147         void *data = reply.get_vendor_data();
    148         int len = reply.get_vendor_data_len();
    149 
    150         ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
    151                 sizeof(*mCapabilities));
    152 
    153         memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
    154 
    155         return NL_OK;
    156     }
    157 };
    158 
    159 
    160 class RttCommand : public WifiCommand
    161 {
    162     unsigned numRttParams;
    163     int mCompleted;
    164     int currentIdx;
    165     int totalCnt;
    166     static const int MAX_RESULTS = 1024;
    167     wifi_rtt_result *rttResults[MAX_RESULTS];
    168     wifi_rtt_config *rttParams;
    169     wifi_rtt_event_handler rttHandler;
    170 public:
    171     RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
    172             wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
    173         : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
    174         rttHandler(handler)
    175     {
    176         memset(rttResults, 0, sizeof(rttResults));
    177         currentIdx = 0;
    178         mCompleted = 0;
    179         totalCnt = 0;
    180     }
    181 
    182     RttCommand(wifi_interface_handle iface, int id)
    183         : WifiCommand("RttCommand", iface, id)
    184     {
    185         currentIdx = 0;
    186         mCompleted = 0;
    187         totalCnt = 0;
    188         numRttParams = 0;
    189     }
    190 
    191     int createSetupRequest(WifiRequest& request) {
    192         int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
    193         if (result < 0) {
    194             return result;
    195         }
    196 
    197         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    198         result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
    199         if (result < 0) {
    200             return result;
    201         }
    202         nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
    203         for (unsigned i = 0; i < numRttParams; i++) {
    204             nlattr *attr2 = request.attr_start(i);
    205             if (attr2 == NULL) {
    206                 return WIFI_ERROR_OUT_OF_MEMORY;
    207             }
    208 
    209             result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
    210             if (result < 0) {
    211                 return result;
    212             }
    213 
    214             result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
    215             if (result < 0) {
    216                 return result;
    217             }
    218 
    219             result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
    220             if (result < 0) {
    221                 return result;
    222             }
    223 
    224             result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
    225                     sizeof(wifi_channel_info));
    226             if (result < 0) {
    227                 return result;
    228             }
    229 
    230             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST, rttParams[i].num_burst);
    231             if (result < 0) {
    232                 return result;
    233             }
    234 
    235             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
    236                     rttParams[i].num_frames_per_burst);
    237             if (result < 0) {
    238                 return result;
    239             }
    240 
    241             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
    242                     rttParams[i].num_retries_per_rtt_frame);
    243             if (result < 0) {
    244                 return result;
    245             }
    246 
    247             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
    248                     rttParams[i].num_retries_per_ftmr);
    249             if (result < 0) {
    250                 return result;
    251             }
    252 
    253             result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD,
    254                     rttParams[i].burst_period);
    255             if (result < 0) {
    256                 return result;
    257             }
    258 
    259             result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION,
    260                     rttParams[i].burst_duration);
    261             if (result < 0) {
    262                 return result;
    263             }
    264 
    265             result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI,
    266                     rttParams[i].LCI_request);
    267             if (result < 0) {
    268                 return result;
    269             }
    270 
    271             result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR,
    272                     rttParams[i].LCR_request);
    273             if (result < 0) {
    274                 return result;
    275             }
    276 
    277             result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW,
    278                     rttParams[i].bw);
    279             if (result < 0) {
    280                 return result;
    281             }
    282 
    283             result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE,
    284                     rttParams[i].preamble);
    285             if (result < 0) {
    286                 return result;
    287             }
    288             request.attr_end(attr2);
    289         }
    290 
    291         request.attr_end(rtt_config);
    292         request.attr_end(data);
    293         return WIFI_SUCCESS;
    294     }
    295 
    296     int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
    297         int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
    298         if (result < 0) {
    299             return result;
    300         }
    301 
    302         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    303         request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
    304         for(unsigned i = 0; i < num_devices; i++) {
    305             result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
    306             if (result < 0) {
    307                 return result;
    308             }
    309         }
    310         request.attr_end(data);
    311         return result;
    312     }
    313     int start() {
    314         ALOGD("Setting RTT configuration");
    315         WifiRequest request(familyId(), ifaceId());
    316         int result = createSetupRequest(request);
    317         if (result != WIFI_SUCCESS) {
    318             ALOGE("failed to create setup request; result = %d", result);
    319             return result;
    320         }
    321 
    322         result = requestResponse(request);
    323         if (result != WIFI_SUCCESS) {
    324             ALOGE("failed to configure RTT setup; result = %d", result);
    325             return result;
    326         }
    327 
    328         registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
    329         ALOGI("Successfully started RTT operation");
    330         return result;
    331     }
    332 
    333     virtual int cancel() {
    334         ALOGD("Stopping RTT");
    335 
    336         WifiRequest request(familyId(), ifaceId());
    337         int result = createTeardownRequest(request, 0, NULL);
    338         if (result != WIFI_SUCCESS) {
    339             ALOGE("failed to create stop request; result = %d", result);
    340         } else {
    341             result = requestResponse(request);
    342             if (result != WIFI_SUCCESS) {
    343                 ALOGE("failed to stop scan; result = %d", result);
    344             }
    345         }
    346 
    347         unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
    348         return WIFI_SUCCESS;
    349     }
    350 
    351     int cancel_specific(unsigned num_devices, mac_addr addr[]) {
    352         ALOGE("Stopping RTT");
    353 
    354         WifiRequest request(familyId(), ifaceId());
    355         int result = createTeardownRequest(request, num_devices, addr);
    356         if (result != WIFI_SUCCESS) {
    357             ALOGE("failed to create stop request; result = %d", result);
    358         } else {
    359             result = requestResponse(request);
    360             if (result != WIFI_SUCCESS) {
    361                 ALOGE("failed to stop RTT; result = %d", result);
    362             }
    363         }
    364 
    365         unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
    366         return WIFI_SUCCESS;
    367     }
    368 
    369     virtual int handleResponse(WifiEvent& reply) {
    370         /* Nothing to do on response! */
    371         return NL_SKIP;
    372     }
    373 
    374     virtual int handleEvent(WifiEvent& event) {
    375         ALOGI("Got an RTT event");
    376         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
    377         int len = event.get_vendor_data_len();
    378         if (vendor_data == NULL || len == 0) {
    379             ALOGI("No rtt results found");
    380         }
    381         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
    382             if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
    383                 mCompleted = it.get_u32();
    384                 ALOGI("retrieved completed flag : %d\n", mCompleted);
    385             } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
    386                 int result_cnt = 0;
    387                 mac_addr bssid;
    388                 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
    389                     if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
    390                         memcpy(bssid, it2.get_data(), sizeof(mac_addr));
    391                         ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
    392                                 bssid[0],
    393                                 bssid[1],
    394                                 bssid[2],
    395                                 bssid[3],
    396                                 bssid[4],
    397                                 bssid[5]);
    398                     } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
    399                         result_cnt = it2.get_u32();
    400                         ALOGI("retrieved result_cnt : %d\n", result_cnt);
    401                     } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
    402                         int result_len = it2.get_len();
    403                         rttResults[currentIdx] =  (wifi_rtt_result *)malloc(it2.get_len());
    404                         wifi_rtt_result *rtt_result = rttResults[currentIdx];
    405                         if (rtt_result == NULL) {
    406                             mCompleted = 1;
    407                             ALOGE("failed to allocate the wifi_rtt_result\n");
    408                             break;
    409                         }
    410                         memcpy(rtt_result, it2.get_data(), it2.get_len());
    411                         result_len -= sizeof(wifi_rtt_result);
    412                         if (result_len > 0) {
    413                             result_len -= sizeof(wifi_rtt_result);
    414                             dot11_rm_ie_t *ele_1;
    415                             dot11_rm_ie_t *ele_2;
    416                             /* The result has LCI or LCR element */
    417                             ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
    418                             if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
    419                                 if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
    420                                     rtt_result->LCI = (wifi_information_element *)ele_1;
    421                                     result_len -= (ele_1->len + DOT11_HDR_LEN);
    422                                     /* get a next rm ie */
    423                                     if (result_len > 0) {
    424                                         ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
    425                                         if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
    426                                                 (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
    427                                             rtt_result->LCR = (wifi_information_element *)ele_2;
    428                                         }
    429                                     }
    430                                 } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
    431                                     rtt_result->LCR = (wifi_information_element *)ele_1;
    432                                     result_len -= (ele_1->len + DOT11_HDR_LEN);
    433                                     /* get a next rm ie */
    434                                     if (result_len > 0) {
    435                                         ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
    436                                         if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
    437                                                 (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
    438                                             rtt_result->LCI = (wifi_information_element *)ele_2;
    439                                         }
    440                                     }
    441                                 }
    442                             }
    443                         }
    444                         totalCnt++;
    445                         ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
    446                                 "\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
    447                                 "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
    448                                 "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
    449                                 rtt_result->burst_num, rtt_result->measurement_number,
    450                                 rtt_result->success_number, rtt_result->number_per_burst_peer,
    451                                 get_err_info(rtt_result->status), rtt_result->retry_after_duration,
    452                                 rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
    453                                 rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance,
    454                                 rtt_result->burst_duration, rtt_result->negotiated_burst_num);
    455                         currentIdx++;
    456                     }
    457                 }
    458             }
    459 
    460         }
    461         if (mCompleted) {
    462             unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
    463             (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
    464             for (int i = 0; i < currentIdx; i++) {
    465                 free(rttResults[i]);
    466                 rttResults[i] = NULL;
    467             }
    468             totalCnt = currentIdx = 0;
    469             WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
    470             if (cmd)
    471                 cmd->releaseRef();
    472         }
    473         return NL_SKIP;
    474     }
    475 };
    476 
    477 
    478 /* API to request RTT measurement */
    479 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
    480         unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
    481 {
    482     wifi_handle handle = getWifiHandle(iface);
    483 
    484     RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
    485     wifi_register_cmd(handle, id, cmd);
    486     return (wifi_error)cmd->start();
    487 }
    488 
    489 /* API to cancel RTT measurements */
    490 wifi_error wifi_rtt_range_cancel(wifi_request_id id,  wifi_interface_handle iface,
    491         unsigned num_devices, mac_addr addr[])
    492 {
    493     wifi_handle handle = getWifiHandle(iface);
    494     RttCommand *cmd = new RttCommand(iface, id);
    495     if (cmd) {
    496         cmd->cancel_specific(num_devices, addr);
    497         cmd->releaseRef();
    498         return WIFI_SUCCESS;
    499     }
    500     return WIFI_ERROR_INVALID_ARGS;
    501 }
    502 
    503 /* API to get RTT capability */
    504 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
    505         wifi_rtt_capabilities *capabilities)
    506 {
    507     GetRttCapabilitiesCommand command(iface, capabilities);
    508     return (wifi_error) command.requestResponse();
    509 }
    510