Home | History | Annotate | Download | only in wifi_hal
      1 /* Copyright (c) 2014, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions
      5  * are met:
      6  *  * Redistributions of source code must retain the above copyright
      7  *    notice, this list of conditions and the following disclaimer.
      8  *  * Redistributions in binary form must reproduce the above copyright
      9  *    notice, this list of conditions and the following disclaimer in
     10  *    the documentation and/or other materials provided with the
     11  *    distribution.
     12  *  * Neither the name of The Linux Foundation nor the names of its
     13  *    contributors may be used to endorse or promote products derived
     14  *    from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "sync.h"
     30 #define LOG_TAG  "WifiHAL"
     31 #include <utils/Log.h>
     32 #include <time.h>
     33 
     34 #include "ifaceeventhandler.h"
     35 
     36 /* Used to handle NL command events from driver/firmware. */
     37 IfaceEventHandlerCommand *mwifiEventHandler = NULL;
     38 
     39 /* Set the interface event monitor handler*/
     40 wifi_error wifi_set_iface_event_handler(wifi_request_id id,
     41                                         wifi_interface_handle iface,
     42                                         wifi_event_handler eh)
     43 {
     44     int i, numAp, ret = 0;
     45     interface_info *ifaceInfo = getIfaceInfo(iface);
     46     wifi_handle wifiHandle = getWifiHandle(iface);
     47 
     48     ALOGE("Setting iface event handler, halHandle = %p", wifiHandle);
     49 
     50     /* Check if a similar request to set iface event handler was made earlier.
     51      * Right now we don't differentiate between the case where (i) the new
     52      * Request Id is different from the current one vs (ii) both new and
     53      * Request Ids are the same.
     54      */
     55     if (mwifiEventHandler)
     56     {
     57         if (id == mwifiEventHandler->get_request_id()) {
     58             ALOGE("%s: Iface Event Handler Set for request Id %d is still"
     59                 "running. Exit", __func__, id);
     60             return WIFI_ERROR_TOO_MANY_REQUESTS;
     61         } else {
     62             ALOGE("%s: Iface Event Handler Set for a different Request "
     63                 "Id:%d is requested. Not supported. Exit", __func__, id);
     64             return WIFI_ERROR_NOT_SUPPORTED;
     65         }
     66     }
     67 
     68     mwifiEventHandler = new IfaceEventHandlerCommand(
     69                     wifiHandle,
     70                     id,
     71                     NL80211_CMD_REG_CHANGE);
     72     if (mwifiEventHandler == NULL) {
     73         ALOGE("%s: Error mwifiEventHandler NULL", __func__);
     74         return WIFI_ERROR_UNKNOWN;
     75     }
     76     mwifiEventHandler->setCallbackHandler(eh);
     77 
     78 cleanup:
     79     return (wifi_error)ret;
     80 }
     81 
     82 /* Reset monitoring for the NL event*/
     83 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
     84                                           wifi_interface_handle iface)
     85 {
     86     int ret = 0;
     87 
     88     if (mwifiEventHandler)
     89     {
     90         if (id == mwifiEventHandler->get_request_id()) {
     91             ALOGI("Delete Object mwifiEventHandler for id = %d", id);
     92             delete mwifiEventHandler;
     93             mwifiEventHandler = NULL;
     94         } else {
     95             ALOGE("%s: Iface Event Handler Set for a different Request "
     96                 "Id:%d is requested. Not supported. Exit", __func__, id);
     97             return WIFI_ERROR_NOT_SUPPORTED;
     98         }
     99     } else {
    100         ALOGI("Object mwifiEventHandler for id = %d already Deleted", id);
    101     }
    102 
    103 cleanup:
    104     return (wifi_error)ret;
    105 }
    106 
    107 /* This function will be the main handler for the registered incoming
    108  * (from driver) Commads. Calls the appropriate callback handler after
    109  * parsing the vendor data.
    110  */
    111 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
    112 {
    113     int ret = WIFI_SUCCESS;
    114 
    115     wifiEventHandler::handleEvent(event);
    116 
    117     switch(mSubcmd)
    118     {
    119         case NL80211_CMD_REG_CHANGE:
    120         {
    121             char code[2];
    122             memset(&code[0], 0, 2);
    123             if(tb[NL80211_ATTR_REG_ALPHA2])
    124             {
    125                 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
    126             } else {
    127                 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
    128             }
    129             ALOGI("Country : %c%c", code[0], code[1]);
    130             if(mHandler.on_country_code_changed)
    131             {
    132                 mHandler.on_country_code_changed(code);
    133             }
    134         }
    135         break;
    136         default:
    137             ALOGI("NL Event : %d Not supported", mSubcmd);
    138     }
    139 
    140     return NL_SKIP;
    141 }
    142 
    143 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
    144         : wifiEventHandler(handle, id, subcmd)
    145 {
    146     ALOGD("wifiEventHandler %p constructed", this);
    147     registerHandler(mSubcmd);
    148     memset(&mHandler, 0, sizeof(wifi_event_handler));
    149     mEventData = NULL;
    150     mDataLen = 0;
    151 }
    152 
    153 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
    154 {
    155     ALOGD("IfaceEventHandlerCommand %p destructor", this);
    156     unregisterHandler(mSubcmd);
    157 }
    158 
    159 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
    160 {
    161     mHandler = nHandler;
    162 }
    163 
    164 int wifiEventHandler::get_request_id()
    165 {
    166     return mRequestId;
    167 }
    168 
    169 int IfaceEventHandlerCommand::get_request_id()
    170 {
    171     return wifiEventHandler::get_request_id();
    172 }
    173 
    174 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
    175         : WifiCommand(handle, id)
    176 {
    177     mRequestId = id;
    178     mSubcmd = subcmd;
    179     registerHandler(mSubcmd);
    180     ALOGD("wifiEventHandler %p constructed", this);
    181 }
    182 
    183 wifiEventHandler::~wifiEventHandler()
    184 {
    185     ALOGD("wifiEventHandler %p destructor", this);
    186     unregisterHandler(mSubcmd);
    187 }
    188 
    189 int wifiEventHandler::handleEvent(WifiEvent &event)
    190 {
    191     ALOGI("wifiEventHandler::handleEvent");
    192     struct genlmsghdr *gnlh = event.header();
    193     mSubcmd = gnlh->cmd;
    194     nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    195             genlmsg_attrlen(gnlh, 0), NULL);
    196     ALOGI("Got NL Event : %d from the Driver.", gnlh->cmd);
    197 
    198     return NL_SKIP;
    199 }
    200 
    201 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
    202                                   u32 subcmd)
    203         : WifiVendorCommand(handle, id, vendor_id, subcmd)
    204 {
    205     ALOGD("WifihalGeneric %p constructed", this);
    206     /* Initialize the member data variables here */
    207     mSet = 0;
    208     mSetSizeMax = 0;
    209     mSetSizePtr = NULL;
    210     mConcurrencySet = 0;
    211 }
    212 
    213 WifihalGeneric::~WifihalGeneric()
    214 {
    215     ALOGD("WifihalGeneric %p destructor", this);
    216 }
    217 
    218 int WifihalGeneric::requestResponse()
    219 {
    220     return WifiCommand::requestResponse(mMsg);
    221 }
    222 
    223 int WifihalGeneric::handleResponse(WifiEvent &reply)
    224 {
    225     ALOGI("Got a Wi-Fi HAL module message from Driver");
    226     int i = 0;
    227     u32 status;
    228     WifiVendorCommand::handleResponse(reply);
    229 
    230     // Parse the vendordata and get the attribute
    231     switch(mSubcmd)
    232     {
    233         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
    234             {
    235                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
    236                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
    237                         (struct nlattr *)mVendorData,
    238                         mDataLen, NULL);
    239 
    240                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
    241                 {
    242                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
    243                     return WIFI_ERROR_INVALID_ARGS;
    244                 }
    245                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
    246                 ALOGI("Supported feature set : %x", mSet);
    247 
    248                 break;
    249             }
    250         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
    251             {
    252                 struct nlattr *tb_vendor[
    253                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
    254                 nla_parse(tb_vendor,
    255                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
    256                     (struct nlattr *)mVendorData,mDataLen, NULL);
    257 
    258                 if (tb_vendor[
    259                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
    260                     u32 val;
    261                     val = nla_get_u32(
    262                         tb_vendor[
    263                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
    264 
    265                     ALOGD("%s: Num of concurrency combinations: %d",
    266                         __func__, val);
    267                     val = val > (unsigned int)mSetSizeMax ?
    268                           (unsigned int)mSetSizeMax : val;
    269                     *mSetSizePtr = val;
    270 
    271                     /* Extract the list of channels. */
    272                     if (*mSetSizePtr > 0 &&
    273                         tb_vendor[
    274                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
    275                         nla_memcpy(mConcurrencySet,
    276                             tb_vendor[
    277                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
    278                             sizeof(feature_set) * (*mSetSizePtr));
    279                     }
    280 
    281                     ALOGD("%s: Get concurrency matrix response received.",
    282                         __func__);
    283                     ALOGD("%s: Num of concurrency combinations : %d",
    284                         __func__, *mSetSizePtr);
    285                     ALOGD("%s: List of valid concurrency combinations is: ",
    286                         __func__);
    287                     for(i = 0; i < *mSetSizePtr; i++)
    288                     {
    289                         ALOGD("%x", *(mConcurrencySet + i));
    290                     }
    291                 }
    292             }
    293             break;
    294         default :
    295             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
    296     }
    297     return NL_SKIP;
    298 }
    299 
    300 void WifihalGeneric::getResponseparams(feature_set *pset)
    301 {
    302     *pset = mSet;
    303 }
    304 
    305 void WifihalGeneric::setMaxSetSize(int set_size_max) {
    306     mSetSizeMax = set_size_max;
    307 }
    308 
    309 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
    310     mConcurrencySet = set;
    311 }
    312 
    313 void WifihalGeneric::setSizePtr(int *set_size) {
    314     mSetSizePtr = set_size;
    315 }
    316