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