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     /* TODO: check for multiple handlers? */
     61 
     62     if (info->num_event_cb < info->alloc_event_cb) {
     63         info->event_cb[info->num_event_cb].nl_cmd  = cmd;
     64         info->event_cb[info->num_event_cb].vendor_id  = 0;
     65         info->event_cb[info->num_event_cb].vendor_subcmd  = 0;
     66         info->event_cb[info->num_event_cb].cb_func = func;
     67         info->event_cb[info->num_event_cb].cb_arg  = arg;
     68         info->num_event_cb++;
     69         ALOGI("Successfully added event handler %p for command %d", func, cmd);
     70         return WIFI_SUCCESS;
     71     } else {
     72         return WIFI_ERROR_OUT_OF_MEMORY;
     73     }
     74 }
     75 
     76 wifi_error wifi_register_vendor_handler(wifi_handle handle,
     77         uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
     78 {
     79     hal_info *info = (hal_info *)handle;
     80 
     81     for (int i = 0; i < info->num_event_cb; i++) {
     82         if(info->event_cb[info->num_event_cb].vendor_id  == id &&
     83            info->event_cb[info->num_event_cb].vendor_subcmd == subcmd)
     84         {
     85             info->event_cb[info->num_event_cb].cb_func = func;
     86             info->event_cb[info->num_event_cb].cb_arg  = arg;
     87             ALOGI("Updated event handler %p for vendor 0x%0x, subcmd 0x%0x"
     88                 " and arg %p", func, id, subcmd, arg);
     89             return WIFI_SUCCESS;
     90         }
     91     }
     92 
     93     if (info->num_event_cb < info->alloc_event_cb) {
     94         info->event_cb[info->num_event_cb].nl_cmd  = NL80211_CMD_VENDOR;
     95         info->event_cb[info->num_event_cb].vendor_id  = id;
     96         info->event_cb[info->num_event_cb].vendor_subcmd  = subcmd;
     97         info->event_cb[info->num_event_cb].cb_func = func;
     98         info->event_cb[info->num_event_cb].cb_arg  = arg;
     99         info->num_event_cb++;
    100         ALOGI("Added event handler %p for vendor 0x%0x, subcmd 0x%0x and arg"
    101             " %p", func, id, subcmd, arg);
    102         return WIFI_SUCCESS;
    103     } else {
    104         return WIFI_ERROR_OUT_OF_MEMORY;
    105     }
    106 }
    107 
    108 void wifi_unregister_handler(wifi_handle handle, int cmd)
    109 {
    110     hal_info *info = (hal_info *)handle;
    111 
    112     if (cmd == NL80211_CMD_VENDOR) {
    113         ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers");
    114     }
    115 
    116     for (int i = 0; i < info->num_event_cb; i++) {
    117         if (info->event_cb[i].nl_cmd == cmd) {
    118             memmove(&info->event_cb[i], &info->event_cb[i+1],
    119                 (info->num_event_cb - i) * sizeof(cb_info));
    120             info->num_event_cb--;
    121             ALOGI("Successfully removed event handler for command %d", cmd);
    122             return;
    123         }
    124     }
    125 }
    126 
    127 void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
    128 {
    129     hal_info *info = (hal_info *)handle;
    130 
    131     for (int i = 0; i < info->num_event_cb; i++) {
    132 
    133         if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
    134                 && info->event_cb[i].vendor_id == id
    135                 && info->event_cb[i].vendor_subcmd == subcmd) {
    136 
    137             memmove(&info->event_cb[i], &info->event_cb[i+1],
    138                 (info->num_event_cb - i) * sizeof(cb_info));
    139             info->num_event_cb--;
    140             ALOGI("Successfully removed event handler for vendor 0x%0x", id);
    141             return;
    142         }
    143     }
    144 }
    145 
    146 
    147 wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
    148 {
    149     hal_info *info = (hal_info *)handle;
    150 
    151     ALOGD("registering command %d", id);
    152 
    153     if (info->num_cmd < info->alloc_cmd) {
    154         info->cmd[info->num_cmd].id   = id;
    155         info->cmd[info->num_cmd].cmd  = cmd;
    156         info->num_cmd++;
    157         ALOGI("Successfully added command %d: %p", id, cmd);
    158         return WIFI_SUCCESS;
    159     } else {
    160         return WIFI_ERROR_OUT_OF_MEMORY;
    161     }
    162 }
    163 
    164 WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id)
    165 {
    166     hal_info *info = (hal_info *)handle;
    167 
    168     ALOGD("un-registering command %d", id);
    169 
    170     for (int i = 0; i < info->num_cmd; i++) {
    171         if (info->cmd[i].id == id) {
    172             WifiCommand *cmd = info->cmd[i].cmd;
    173             memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
    174             info->num_cmd--;
    175             ALOGI("Successfully removed command %d: %p", id, cmd);
    176             return cmd;
    177         }
    178     }
    179 
    180     return NULL;
    181 }
    182 
    183 void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd)
    184 {
    185     hal_info *info = (hal_info *)handle;
    186 
    187     for (int i = 0; i < info->num_cmd; i++) {
    188         if (info->cmd[i].cmd == cmd) {
    189             int id = info->cmd[i].id;
    190             memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
    191             info->num_cmd--;
    192             ALOGI("Successfully removed command %d: %p", id, cmd);
    193             return;
    194         }
    195     }
    196 }
    197 
    198 #ifdef __cplusplus
    199 extern "C"
    200 {
    201 #endif /* __cplusplus */
    202 
    203 void hexdump(char *bytes, u16 len)
    204 {
    205     int i=0;
    206     ALOGI("******HexDump len:%d*********", len);
    207     for (i = 0; ((i + 7) < len); i+=8) {
    208         ALOGI("%02x %02x %02x %02x   %02x %02x %02x %02x",
    209               bytes[i], bytes[i+1],
    210               bytes[i+2], bytes[i+3],
    211               bytes[i+4], bytes[i+5],
    212               bytes[i+6], bytes[i+7]);
    213     }
    214     if ((len - i) >= 4) {
    215         ALOGI("%02x %02x %02x %02x",
    216               bytes[i], bytes[i+1],
    217               bytes[i+2], bytes[i+3]);
    218         i+=4;
    219     }
    220     for (;i < len;i++) {
    221         ALOGI("%02x", bytes[i]);
    222     }
    223     ALOGI("******HexDump End***********");
    224 }
    225 
    226 #ifdef __cplusplus
    227 }
    228 #endif /* __cplusplus */
    229