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 
     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