Home | History | Annotate | Download | only in wifi_hal
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <linux/pkt_sched.h>
     19 #include <netlink/object-api.h>
     20 #include <netlink-types.h>
     21 
     22 #include "wifi_hal.h"
     23 #include "common.h"
     24 #include <netlink-types.h>
     25 
     26 interface_info *getIfaceInfo(wifi_interface_handle handle)
     27 {
     28     return (interface_info *)handle;
     29 }
     30 
     31 wifi_handle getWifiHandle(wifi_interface_handle handle)
     32 {
     33     return getIfaceInfo(handle)->handle;
     34 }
     35 
     36 hal_info *getHalInfo(wifi_handle handle)
     37 {
     38     return (hal_info *)handle;
     39 }
     40 
     41 hal_info *getHalInfo(wifi_interface_handle handle)
     42 {
     43     return getHalInfo(getWifiHandle(handle));
     44 }
     45 
     46 wifi_handle getWifiHandle(hal_info *info)
     47 {
     48     return (wifi_handle)info;
     49 }
     50 
     51 wifi_interface_handle getIfaceHandle(interface_info *info)
     52 {
     53     return (wifi_interface_handle)info;
     54 }
     55 
     56 wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
     57 {
     58     hal_info *info = (hal_info *)handle;
     59 
     60     pthread_mutex_lock(&info->cb_lock);
     61 
     62     wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
     63 
     64     for (int i = 0; i < info->num_event_cb; i++) {
     65         if(info->event_cb[i].nl_cmd == cmd &&
     66            info->event_cb[i].cb_arg == arg) {
     67             info->event_cb[i].cb_func = func;
     68             ALOGI("Updated event handler %p for nl_cmd 0x%0x"
     69                     " and arg %p", func, cmd, arg);
     70             result = WIFI_SUCCESS;
     71         }
     72     }
     73 
     74     if (info->num_event_cb < info->alloc_event_cb) {
     75         info->event_cb[info->num_event_cb].nl_cmd  = cmd;
     76         info->event_cb[info->num_event_cb].vendor_id  = 0;
     77         info->event_cb[info->num_event_cb].vendor_subcmd  = 0;
     78         info->event_cb[info->num_event_cb].cb_func = func;
     79         info->event_cb[info->num_event_cb].cb_arg  = arg;
     80         info->num_event_cb++;
     81         ALOGI("Successfully added event handler %p for command %d", func, cmd);
     82         result = WIFI_SUCCESS;
     83     } else {
     84         result = WIFI_ERROR_OUT_OF_MEMORY;
     85     }
     86 
     87     pthread_mutex_unlock(&info->cb_lock);
     88     return result;
     89 }
     90 
     91 wifi_error wifi_register_vendor_handler(wifi_handle handle,
     92         uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
     93 {
     94     hal_info *info = (hal_info *)handle;
     95 
     96     pthread_mutex_lock(&info->cb_lock);
     97 
     98     wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
     99 
    100     for (int i = 0; i < info->num_event_cb; i++) {
    101         if(info->event_cb[i].vendor_id  == id &&
    102            info->event_cb[i].vendor_subcmd == subcmd)
    103         {
    104             info->event_cb[i].cb_func = func;
    105             info->event_cb[i].cb_arg  = arg;
    106             ALOGI("Updated event handler %p for vendor 0x%0x, subcmd 0x%0x"
    107                 " and arg %p", func, id, subcmd, arg);
    108             result = WIFI_SUCCESS;
    109         }
    110     }
    111 
    112     if (info->num_event_cb < info->alloc_event_cb) {
    113         info->event_cb[info->num_event_cb].nl_cmd  = NL80211_CMD_VENDOR;
    114         info->event_cb[info->num_event_cb].vendor_id  = id;
    115         info->event_cb[info->num_event_cb].vendor_subcmd  = subcmd;
    116         info->event_cb[info->num_event_cb].cb_func = func;
    117         info->event_cb[info->num_event_cb].cb_arg  = arg;
    118         info->num_event_cb++;
    119         ALOGI("Added event handler %p for vendor 0x%0x, subcmd 0x%0x and arg"
    120             " %p", func, id, subcmd, arg);
    121         result = WIFI_SUCCESS;
    122     } else {
    123         result = WIFI_ERROR_OUT_OF_MEMORY;
    124     }
    125 
    126     pthread_mutex_unlock(&info->cb_lock);
    127     return result;
    128 }
    129 
    130 void wifi_unregister_handler(wifi_handle handle, int cmd)
    131 {
    132     hal_info *info = (hal_info *)handle;
    133 
    134     if (cmd == NL80211_CMD_VENDOR) {
    135         ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers");
    136         return;
    137     }
    138 
    139     pthread_mutex_lock(&info->cb_lock);
    140 
    141     for (int i = 0; i < info->num_event_cb; i++) {
    142         if (info->event_cb[i].nl_cmd == cmd) {
    143             if(i < info->num_event_cb-1) {
    144                 /* No need to memmove if only one entry exist and deleting
    145                  * the same, as the num_event_cb will become 0 in this case.
    146                  */
    147                 memmove(&info->event_cb[i], &info->event_cb[i+1],
    148                         (info->num_event_cb - i) * sizeof(cb_info));
    149             }
    150             info->num_event_cb--;
    151             ALOGI("Successfully removed event handler for command %d", cmd);
    152             break;
    153         }
    154     }
    155 
    156     pthread_mutex_unlock(&info->cb_lock);
    157 }
    158 
    159 void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
    160 {
    161     hal_info *info = (hal_info *)handle;
    162 
    163     pthread_mutex_lock(&info->cb_lock);
    164 
    165     for (int i = 0; i < info->num_event_cb; i++) {
    166 
    167         if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
    168                 && info->event_cb[i].vendor_id == id
    169                 && info->event_cb[i].vendor_subcmd == subcmd) {
    170             if(i < info->num_event_cb-1) {
    171                 /* No need to memmove if only one entry exist and deleting
    172                  * the same, as the num_event_cb will become 0 in this case.
    173                  */
    174                 memmove(&info->event_cb[i], &info->event_cb[i+1],
    175                         (info->num_event_cb - i) * sizeof(cb_info));
    176             }
    177             info->num_event_cb--;
    178             ALOGI("Successfully removed event handler for vendor 0x%0x", id);
    179             break;
    180         }
    181     }
    182 
    183     pthread_mutex_unlock(&info->cb_lock);
    184 }
    185 
    186 
    187 wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
    188 {
    189     hal_info *info = (hal_info *)handle;
    190 
    191     ALOGD("registering command %d", id);
    192 
    193     if (info->num_cmd < info->alloc_cmd) {
    194         info->cmd[info->num_cmd].id   = id;
    195         info->cmd[info->num_cmd].cmd  = cmd;
    196         info->num_cmd++;
    197         ALOGI("Successfully added command %d: %p", id, cmd);
    198         return WIFI_SUCCESS;
    199     } else {
    200         return WIFI_ERROR_OUT_OF_MEMORY;
    201     }
    202 }
    203 
    204 WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id)
    205 {
    206     hal_info *info = (hal_info *)handle;
    207 
    208     ALOGD("un-registering command %d", id);
    209 
    210     for (int i = 0; i < info->num_cmd; i++) {
    211         if (info->cmd[i].id == id) {
    212             WifiCommand *cmd = info->cmd[i].cmd;
    213             memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
    214             info->num_cmd--;
    215             ALOGI("Successfully removed command %d: %p", id, cmd);
    216             return cmd;
    217         }
    218     }
    219 
    220     return NULL;
    221 }
    222 
    223 void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd)
    224 {
    225     hal_info *info = (hal_info *)handle;
    226 
    227     for (int i = 0; i < info->num_cmd; i++) {
    228         if (info->cmd[i].cmd == cmd) {
    229             int id = info->cmd[i].id;
    230             memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
    231             info->num_cmd--;
    232             ALOGI("Successfully removed command %d: %p", id, cmd);
    233             return;
    234         }
    235     }
    236 }
    237 
    238 #ifdef __cplusplus
    239 extern "C"
    240 {
    241 #endif /* __cplusplus */
    242 
    243 void hexdump(void *buf, u16 len)
    244 {
    245     int i=0;
    246     char *bytes = (char *)buf;
    247     ALOGI("******HexDump len:%d*********", len);
    248     for (i = 0; ((i + 7) < len); i+=8) {
    249         ALOGI("%02x %02x %02x %02x   %02x %02x %02x %02x",
    250               bytes[i], bytes[i+1],
    251               bytes[i+2], bytes[i+3],
    252               bytes[i+4], bytes[i+5],
    253               bytes[i+6], bytes[i+7]);
    254     }
    255     if ((len - i) >= 4) {
    256         ALOGI("%02x %02x %02x %02x",
    257               bytes[i], bytes[i+1],
    258               bytes[i+2], bytes[i+3]);
    259         i+=4;
    260     }
    261     for (;i < len;i++) {
    262         ALOGI("%02x", bytes[i]);
    263     }
    264     ALOGI("******HexDump End***********");
    265 }
    266 
    267 #ifdef __cplusplus
    268 }
    269 #endif /* __cplusplus */
    270