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 ret = 0;
     45     wifi_handle wifiHandle = getWifiHandle(iface);
     46 
     47     /* Check if a similar request to set iface event handler was made earlier.
     48      * Right now we don't differentiate between the case where (i) the new
     49      * Request Id is different from the current one vs (ii) both new and
     50      * Request Ids are the same.
     51      */
     52     if (mwifiEventHandler)
     53     {
     54         if (id == mwifiEventHandler->get_request_id()) {
     55             ALOGE("%s: Iface Event Handler Set for request Id %d is still"
     56                 "running. Exit", __func__, id);
     57             return WIFI_ERROR_TOO_MANY_REQUESTS;
     58         } else {
     59             ALOGE("%s: Iface Event Handler Set for a different Request "
     60                 "Id:%d is requested. Not supported. Exit", __func__, id);
     61             return WIFI_ERROR_NOT_SUPPORTED;
     62         }
     63     }
     64 
     65     mwifiEventHandler = new IfaceEventHandlerCommand(
     66                     wifiHandle,
     67                     id,
     68                     NL80211_CMD_REG_CHANGE);
     69     if (mwifiEventHandler == NULL) {
     70         ALOGE("%s: Error mwifiEventHandler NULL", __func__);
     71         return WIFI_ERROR_UNKNOWN;
     72     }
     73     mwifiEventHandler->setCallbackHandler(eh);
     74 
     75     return (wifi_error)ret;
     76 }
     77 
     78 /* Reset monitoring for the NL event*/
     79 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
     80                                           wifi_interface_handle iface)
     81 {
     82     int ret = 0;
     83 
     84     if (mwifiEventHandler)
     85     {
     86         if (id == mwifiEventHandler->get_request_id()) {
     87             ALOGV("Delete Object mwifiEventHandler for id = %d", id);
     88             delete mwifiEventHandler;
     89             mwifiEventHandler = NULL;
     90         } else {
     91             ALOGE("%s: Iface Event Handler Set for a different Request "
     92                 "Id:%d is requested. Not supported. Exit", __func__, id);
     93             return WIFI_ERROR_NOT_SUPPORTED;
     94         }
     95     } else {
     96         ALOGV("Object mwifiEventHandler for id = %d already Deleted", id);
     97     }
     98 
     99     return (wifi_error)ret;
    100 }
    101 
    102 /* This function will be the main handler for the registered incoming
    103  * (from driver) Commads. Calls the appropriate callback handler after
    104  * parsing the vendor data.
    105  */
    106 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
    107 {
    108     wifiEventHandler::handleEvent(event);
    109 
    110     switch(mSubcmd)
    111     {
    112         case NL80211_CMD_REG_CHANGE:
    113         {
    114             char code[2];
    115             memset(&code[0], 0, 2);
    116             if(tb[NL80211_ATTR_REG_ALPHA2])
    117             {
    118                 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
    119             } else {
    120                 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
    121             }
    122             ALOGV("Country : %c%c", code[0], code[1]);
    123             if(mHandler.on_country_code_changed)
    124             {
    125                 mHandler.on_country_code_changed(code);
    126             }
    127         }
    128         break;
    129         default:
    130             ALOGV("NL Event : %d Not supported", mSubcmd);
    131     }
    132 
    133     return NL_SKIP;
    134 }
    135 
    136 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
    137         : wifiEventHandler(handle, id, subcmd)
    138 {
    139     ALOGV("wifiEventHandler %p constructed", this);
    140     registerHandler(mSubcmd);
    141     memset(&mHandler, 0, sizeof(wifi_event_handler));
    142     mEventData = NULL;
    143     mDataLen = 0;
    144 }
    145 
    146 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
    147 {
    148     ALOGV("IfaceEventHandlerCommand %p destructor", this);
    149     unregisterHandler(mSubcmd);
    150 }
    151 
    152 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
    153 {
    154     mHandler = nHandler;
    155 }
    156 
    157 int wifiEventHandler::get_request_id()
    158 {
    159     return mRequestId;
    160 }
    161 
    162 int IfaceEventHandlerCommand::get_request_id()
    163 {
    164     return wifiEventHandler::get_request_id();
    165 }
    166 
    167 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
    168         : WifiCommand(handle, id)
    169 {
    170     mRequestId = id;
    171     mSubcmd = subcmd;
    172     registerHandler(mSubcmd);
    173     ALOGV("wifiEventHandler %p constructed", this);
    174 }
    175 
    176 wifiEventHandler::~wifiEventHandler()
    177 {
    178     ALOGV("wifiEventHandler %p destructor", this);
    179     unregisterHandler(mSubcmd);
    180 }
    181 
    182 int wifiEventHandler::handleEvent(WifiEvent &event)
    183 {
    184     struct genlmsghdr *gnlh = event.header();
    185     mSubcmd = gnlh->cmd;
    186     nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    187             genlmsg_attrlen(gnlh, 0), NULL);
    188     ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd);
    189 
    190     return NL_SKIP;
    191 }
    192 
    193 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
    194                                   u32 subcmd)
    195         : WifiVendorCommand(handle, id, vendor_id, subcmd)
    196 {
    197     /* Initialize the member data variables here */
    198     mSet = 0;
    199     mSetSizeMax = 0;
    200     mSetSizePtr = NULL;
    201     mConcurrencySet = 0;
    202     filterVersion = 0;
    203     filterLength = 0;
    204     firmware_bus_max_size = 0;
    205 }
    206 
    207 WifihalGeneric::~WifihalGeneric()
    208 {
    209 }
    210 
    211 int WifihalGeneric::requestResponse()
    212 {
    213     return WifiCommand::requestResponse(mMsg);
    214 }
    215 
    216 int WifihalGeneric::handleResponse(WifiEvent &reply)
    217 {
    218     ALOGV("Got a Wi-Fi HAL module message from Driver");
    219     int i = 0;
    220     WifiVendorCommand::handleResponse(reply);
    221 
    222     // Parse the vendordata and get the attribute
    223     switch(mSubcmd)
    224     {
    225         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
    226             {
    227                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
    228                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
    229                         (struct nlattr *)mVendorData,
    230                         mDataLen, NULL);
    231 
    232                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
    233                 {
    234                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
    235                     return WIFI_ERROR_INVALID_ARGS;
    236                 }
    237                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
    238                 ALOGV("Supported feature set : %x", mSet);
    239 
    240                 break;
    241             }
    242         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
    243             {
    244                 struct nlattr *tb_vendor[
    245                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
    246                 nla_parse(tb_vendor,
    247                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
    248                     (struct nlattr *)mVendorData,mDataLen, NULL);
    249 
    250                 if (tb_vendor[
    251                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
    252                     u32 val;
    253                     val = nla_get_u32(
    254                         tb_vendor[
    255                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
    256 
    257                     ALOGV("%s: Num of concurrency combinations: %d",
    258                         __func__, val);
    259                     val = val > (unsigned int)mSetSizeMax ?
    260                           (unsigned int)mSetSizeMax : val;
    261                     *mSetSizePtr = val;
    262 
    263                     /* Extract the list of channels. */
    264                     if (*mSetSizePtr > 0 &&
    265                         tb_vendor[
    266                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
    267                         nla_memcpy(mConcurrencySet,
    268                             tb_vendor[
    269                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
    270                             sizeof(feature_set) * (*mSetSizePtr));
    271                     }
    272 
    273                     ALOGV("%s: Get concurrency matrix response received.",
    274                         __func__);
    275                     ALOGV("%s: Num of concurrency combinations : %d",
    276                         __func__, *mSetSizePtr);
    277                     ALOGV("%s: List of valid concurrency combinations is: ",
    278                         __func__);
    279                     for(i = 0; i < *mSetSizePtr; i++)
    280                     {
    281                         ALOGV("%x", *(mConcurrencySet + i));
    282                     }
    283                 }
    284             }
    285             break;
    286         case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
    287             {
    288                 struct nlattr *tb_vendor[
    289                         QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
    290                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
    291                         (struct nlattr *)mVendorData,
    292                         mDataLen, NULL);
    293 
    294                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
    295                 {
    296                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
    297                           " not found", __FUNCTION__);
    298                     return WIFI_ERROR_INVALID_ARGS;
    299                 }
    300                 filterVersion = nla_get_u32(
    301                        tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
    302                 ALOGV("Current version : %u", filterVersion);
    303 
    304                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
    305                 {
    306                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
    307                           " not found", __FUNCTION__);
    308                     return WIFI_ERROR_INVALID_ARGS;
    309                 }
    310                 filterLength = nla_get_u32(
    311                     tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
    312                 ALOGV("Max filter length Supported : %u", filterLength);
    313 
    314             }
    315             break;
    316         case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
    317             {
    318                 struct nlattr *tb_vendor[
    319                         QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
    320                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
    321                           (struct nlattr *)mVendorData, mDataLen, NULL);
    322 
    323                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
    324                 {
    325                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
    326                           " not found", __FUNCTION__);
    327                     return WIFI_ERROR_INVALID_ARGS;
    328                 }
    329                 firmware_bus_max_size = nla_get_u32(
    330                        tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
    331                 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
    332             }
    333             break;
    334         default :
    335             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
    336     }
    337     return NL_SKIP;
    338 }
    339 
    340 void WifihalGeneric::getResponseparams(feature_set *pset)
    341 {
    342     *pset = mSet;
    343 }
    344 
    345 void WifihalGeneric::setMaxSetSize(int set_size_max) {
    346     mSetSizeMax = set_size_max;
    347 }
    348 
    349 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
    350     mConcurrencySet = set;
    351 }
    352 
    353 void WifihalGeneric::setSizePtr(int *set_size) {
    354     mSetSizePtr = set_size;
    355 }
    356 
    357 int WifihalGeneric::getFilterVersion() {
    358     return filterVersion;
    359 }
    360 
    361 int WifihalGeneric::getFilterLength() {
    362     return filterLength;
    363 }
    364 
    365 int WifihalGeneric::getBusSize() {
    366     return firmware_bus_max_size;
    367 }
    368