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