1 2 #include <stdlib.h> 3 #include <linux/pkt_sched.h> 4 #include <netlink/object-api.h> 5 #include <netlink/handlers.h> 6 7 #include "wifi_hal.h" 8 #include "common.h" 9 10 interface_info *getIfaceInfo(wifi_interface_handle handle) 11 { 12 return (interface_info *)handle; 13 } 14 15 wifi_handle getWifiHandle(wifi_interface_handle handle) 16 { 17 return getIfaceInfo(handle)->handle; 18 } 19 20 hal_info *getHalInfo(wifi_handle handle) 21 { 22 return (hal_info *)handle; 23 } 24 25 hal_info *getHalInfo(wifi_interface_handle handle) 26 { 27 return getHalInfo(getWifiHandle(handle)); 28 } 29 30 wifi_handle getWifiHandle(hal_info *info) 31 { 32 return (wifi_handle)info; 33 } 34 35 wifi_interface_handle getIfaceHandle(interface_info *info) 36 { 37 return (wifi_interface_handle)info; 38 } 39 40 wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg) 41 { 42 hal_info *info = (hal_info *)handle; 43 44 /* TODO: check for multiple handlers? */ 45 pthread_mutex_lock(&info->cb_lock); 46 47 wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 48 49 if (info->num_event_cb < info->alloc_event_cb) { 50 info->event_cb[info->num_event_cb].nl_cmd = cmd; 51 info->event_cb[info->num_event_cb].vendor_id = 0; 52 info->event_cb[info->num_event_cb].vendor_subcmd = 0; 53 info->event_cb[info->num_event_cb].cb_func = func; 54 info->event_cb[info->num_event_cb].cb_arg = arg; 55 ALOGI("Successfully added event handler %p:%p for command %d at %d", 56 arg, func, cmd, info->num_event_cb); 57 info->num_event_cb++; 58 result = WIFI_SUCCESS; 59 } 60 61 pthread_mutex_unlock(&info->cb_lock); 62 return result; 63 } 64 65 wifi_error wifi_register_vendor_handler(wifi_handle handle, 66 uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg) 67 { 68 hal_info *info = (hal_info *)handle; 69 70 /* TODO: check for multiple handlers? */ 71 pthread_mutex_lock(&info->cb_lock); 72 73 wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 74 75 if (info->num_event_cb < info->alloc_event_cb) { 76 info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR; 77 info->event_cb[info->num_event_cb].vendor_id = id; 78 info->event_cb[info->num_event_cb].vendor_subcmd = subcmd; 79 info->event_cb[info->num_event_cb].cb_func = func; 80 info->event_cb[info->num_event_cb].cb_arg = arg; 81 ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d", 82 arg, func, id, subcmd, info->num_event_cb); 83 info->num_event_cb++; 84 result = WIFI_SUCCESS; 85 } 86 87 pthread_mutex_unlock(&info->cb_lock); 88 return result; 89 } 90 91 void wifi_unregister_handler(wifi_handle handle, int cmd) 92 { 93 hal_info *info = (hal_info *)handle; 94 95 if (cmd == NL80211_CMD_VENDOR) { 96 ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers"); 97 return; 98 } 99 100 pthread_mutex_lock(&info->cb_lock); 101 102 for (int i = 0; i < info->num_event_cb; i++) { 103 if (info->event_cb[i].nl_cmd == cmd) { 104 ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d", 105 info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i); 106 107 memmove(&info->event_cb[i], &info->event_cb[i+1], 108 (info->num_event_cb - i - 1) * sizeof(cb_info)); 109 info->num_event_cb--; 110 break; 111 } 112 } 113 114 pthread_mutex_unlock(&info->cb_lock); 115 } 116 117 void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd) 118 { 119 hal_info *info = (hal_info *)handle; 120 121 pthread_mutex_lock(&info->cb_lock); 122 123 for (int i = 0; i < info->num_event_cb; i++) { 124 125 if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR 126 && info->event_cb[i].vendor_id == id 127 && info->event_cb[i].vendor_subcmd == subcmd) { 128 ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d", 129 info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i); 130 memmove(&info->event_cb[i], &info->event_cb[i+1], 131 (info->num_event_cb - i - 1) * sizeof(cb_info)); 132 info->num_event_cb--; 133 break; 134 } 135 } 136 137 pthread_mutex_unlock(&info->cb_lock); 138 } 139 140 141 wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd) 142 { 143 hal_info *info = (hal_info *)handle; 144 145 ALOGD("registering command %d", id); 146 147 wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 148 149 if (info->num_cmd < info->alloc_cmd) { 150 info->cmd[info->num_cmd].id = id; 151 info->cmd[info->num_cmd].cmd = cmd; 152 ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd); 153 info->num_cmd++; 154 result = WIFI_SUCCESS; 155 } 156 157 return result; 158 } 159 160 WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id) 161 { 162 hal_info *info = (hal_info *)handle; 163 164 ALOGD("un-registering command %d", id); 165 166 WifiCommand *cmd = NULL; 167 168 for (int i = 0; i < info->num_cmd; i++) { 169 if (info->cmd[i].id == id) { 170 cmd = info->cmd[i].cmd; 171 memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); 172 info->num_cmd--; 173 ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); 174 break; 175 } 176 } 177 178 return cmd; 179 } 180 181 WifiCommand *wifi_get_cmd(wifi_handle handle, int id) 182 { 183 hal_info *info = (hal_info *)handle; 184 185 WifiCommand *cmd = NULL; 186 187 for (int i = 0; i < info->num_cmd; i++) { 188 if (info->cmd[i].id == id) { 189 cmd = info->cmd[i].cmd; 190 break; 191 } 192 } 193 194 return cmd; 195 } 196 197 void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd) 198 { 199 hal_info *info = (hal_info *)handle; 200 201 for (int i = 0; i < info->num_cmd; i++) { 202 if (info->cmd[i].cmd == cmd) { 203 int id = info->cmd[i].id; 204 memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); 205 info->num_cmd--; 206 ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); 207 break; 208 } 209 } 210 } 211