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 26 #include "wifi_hal.h" 27 #include "common.h" 28 #include "cpp_bindings.h" 29 30 typedef enum { 31 32 RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, 33 RTT_SUBCMD_CANCEL_CONFIG, 34 RTT_SUBCMD_GETCAPABILITY, 35 } RTT_SUB_COMMAND; 36 37 typedef enum { 38 RTT_ATTRIBUTE_TARGET_CNT, 39 RTT_ATTRIBUTE_TARGET_INFO, 40 RTT_ATTRIBUTE_TARGET_MAC, 41 RTT_ATTRIBUTE_TARGET_TYPE, 42 RTT_ATTRIBUTE_TARGET_PEER, 43 RTT_ATTRIBUTE_TARGET_CHAN, 44 RTT_ATTRIBUTE_TARGET_MODE, 45 RTT_ATTRIBUTE_TARGET_INTERVAL, 46 RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT, 47 RTT_ATTRIBUTE_TARGET_NUM_PKT, 48 RTT_ATTRIBUTE_TARGET_NUM_RETRY, 49 50 } GSCAN_ATTRIBUTE; 51 class GetRttCapabilitiesCommand : public WifiCommand 52 { 53 wifi_rtt_capabilities *mCapabilities; 54 public: 55 GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites) 56 : WifiCommand(iface, 0), mCapabilities(capabitlites) 57 { 58 memset(mCapabilities, 0, sizeof(*mCapabilities)); 59 } 60 61 virtual int create() { 62 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); 63 64 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY); 65 if (ret < 0) { 66 return ret; 67 } 68 69 return ret; 70 } 71 72 protected: 73 virtual int handleResponse(WifiEvent& reply) { 74 75 ALOGD("In GetRttCapabilitiesCommand::handleResponse"); 76 77 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 78 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 79 return NL_SKIP; 80 } 81 82 int id = reply.get_vendor_id(); 83 int subcmd = reply.get_vendor_subcmd(); 84 85 void *data = reply.get_vendor_data(); 86 int len = reply.get_vendor_data_len(); 87 88 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, 89 sizeof(*mCapabilities)); 90 91 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); 92 93 return NL_OK; 94 } 95 }; 96 97 98 class RttCommand : public WifiCommand 99 { 100 unsigned numRttParams; 101 static const int MAX_RESULTS = 64; 102 wifi_rtt_result rttResults[MAX_RESULTS]; 103 wifi_rtt_config *rttParams; 104 wifi_rtt_event_handler rttHandler; 105 public: 106 RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config, 107 wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) 108 : WifiCommand(iface, id), numRttParams(num_rtt_config), rttParams(rtt_config), 109 rttHandler(handler) 110 { } 111 112 113 int createSetupRequest(WifiRequest& request) { 114 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG); 115 if (result < 0) { 116 return result; 117 } 118 119 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 120 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams); 121 if (result < 0) { 122 return result; 123 } 124 nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO); 125 for (unsigned i = 0; i < numRttParams; i++) { 126 127 nlattr *attr2 = request.attr_start(i); 128 if (attr2 == NULL) { 129 return WIFI_ERROR_OUT_OF_MEMORY; 130 } 131 132 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr); 133 if (result < 0) { 134 return result; 135 } 136 result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type); 137 if (result < 0) { 138 return result; 139 } 140 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer); 141 if (result < 0) { 142 return result; 143 } 144 result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel, 145 sizeof(wifi_channel_info)); 146 if (result < 0) { 147 return result; 148 } 149 result = request.put_u8(RTT_ATTRIBUTE_TARGET_MODE, rttParams[i].continuous); 150 if (result < 0) { 151 return result; 152 } 153 result = request.put_u32(RTT_ATTRIBUTE_TARGET_INTERVAL, rttParams[i].interval); 154 if (result < 0) { 155 return result; 156 } 157 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT, 158 rttParams[i].num_measurements); 159 if (result < 0) { 160 return result; 161 } 162 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_PKT, 163 rttParams[i].num_samples_per_measurement); 164 if (result < 0) { 165 return result; 166 } 167 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY, 168 rttParams[i].num_retries_per_measurement); 169 if (result < 0) { 170 return result; 171 } 172 request.attr_end(attr2); 173 } 174 175 request.attr_end(rtt_config); 176 request.attr_end(data); 177 return WIFI_SUCCESS; 178 } 179 180 int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) { 181 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG); 182 if (result < 0) { 183 return result; 184 } 185 186 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 187 request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices); 188 for(unsigned i = 0; i < num_devices; i++) { 189 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]); 190 if (result < 0) { 191 return result; 192 } 193 } 194 request.attr_end(data); 195 return result; 196 } 197 int start() { 198 ALOGD("Setting RTT configuration"); 199 WifiRequest request(familyId(), ifaceId()); 200 int result = createSetupRequest(request); 201 if (result != WIFI_SUCCESS) { 202 ALOGE("failed to create setup request; result = %d", result); 203 return result; 204 } 205 206 result = requestResponse(request); 207 if (result != WIFI_SUCCESS) { 208 ALOGE("failed to configure RTT setup; result = %d", result); 209 return result; 210 } 211 212 registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); 213 ALOGI("Successfully started RTT operation"); 214 return result; 215 } 216 217 virtual int cancel() { 218 ALOGD("Stopping RTT"); 219 220 WifiRequest request(familyId(), ifaceId()); 221 int result = createTeardownRequest(request, 0, NULL); 222 if (result != WIFI_SUCCESS) { 223 ALOGE("failed to create stop request; result = %d", result); 224 } else { 225 result = requestResponse(request); 226 if (result != WIFI_SUCCESS) { 227 ALOGE("failed to stop scan; result = %d", result); 228 } 229 } 230 231 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); 232 return WIFI_SUCCESS; 233 } 234 235 int cancel_specific(unsigned num_devices, mac_addr addr[]) { 236 ALOGD("Stopping scan"); 237 238 WifiRequest request(familyId(), ifaceId()); 239 int result = createTeardownRequest(request, num_devices, addr); 240 if (result != WIFI_SUCCESS) { 241 ALOGE("failed to create stop request; result = %d", result); 242 } else { 243 result = requestResponse(request); 244 if (result != WIFI_SUCCESS) { 245 ALOGE("failed to stop RTT; result = %d", result); 246 } 247 } 248 249 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); 250 return WIFI_SUCCESS; 251 } 252 253 virtual int handleResponse(WifiEvent& reply) { 254 /* Nothing to do on response! */ 255 return NL_SKIP; 256 } 257 258 virtual int handleEvent(WifiEvent& event) { 259 ALOGI("Got an RTT event"); 260 261 // event.log(); 262 263 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 264 int len = event.get_vendor_data_len(); 265 266 if (vendor_data == NULL || len == 0) { 267 ALOGI("No rtt results found"); 268 } 269 270 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE); 271 wifi_unregister_cmd(wifiHandle(), id()); 272 273 memset(rttResults, 0, sizeof(wifi_rtt_result) * MAX_RESULTS); 274 275 int num = len / sizeof(wifi_rtt_result); 276 num = min(MAX_RESULTS, num); 277 memcpy(rttResults, event.get_vendor_data(), num * sizeof(wifi_rtt_result)); 278 ALOGI("Retrieved %d rtt results", num); 279 280 (*rttHandler.on_rtt_results)(id(), num, rttResults); 281 return NL_SKIP; 282 } 283 }; 284 285 286 /* API to request RTT measurement */ 287 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface, 288 unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler) 289 { 290 wifi_handle handle = getWifiHandle(iface); 291 292 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler); 293 wifi_register_cmd(handle, id, cmd); 294 return (wifi_error)cmd->start(); 295 } 296 297 /* API to cancel RTT measurements */ 298 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, 299 unsigned num_devices, mac_addr addr[]) 300 { 301 wifi_handle handle = getWifiHandle(iface); 302 RttCommand *cmd = (RttCommand *)wifi_unregister_cmd(handle, id); 303 if (cmd) { 304 cmd->cancel_specific(num_devices, addr); 305 cmd->releaseRef(); 306 return WIFI_SUCCESS; 307 } 308 309 return WIFI_ERROR_INVALID_ARGS; 310 } 311 312 /* API to get RTT capability */ 313 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, 314 wifi_rtt_capabilities *capabilities) 315 { 316 GetRttCapabilitiesCommand command(iface, capabilities); 317 return (wifi_error) command.requestResponse(); 318 } 319 320 321