11a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 21a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <stdlib.h> 30aa072e53060866de1ddf6510e797470c08fd1a4Vinit Deshapnde#include <linux/pkt_sched.h> 40aa072e53060866de1ddf6510e797470c08fd1a4Vinit Deshapnde#include <netlink/object-api.h> 5642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/handlers.h> 61a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 71a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "wifi_hal.h" 81a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "common.h" 91a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeinterface_info *getIfaceInfo(wifi_interface_handle handle) 111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (interface_info *)handle; 131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_handle getWifiHandle(wifi_interface_handle handle) 161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return getIfaceInfo(handle)->handle; 181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndehal_info *getHalInfo(wifi_handle handle) 211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (hal_info *)handle; 231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndehal_info *getHalInfo(wifi_interface_handle handle) 261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return getHalInfo(getWifiHandle(handle)); 281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_handle getWifiHandle(hal_info *info) 311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_handle)info; 331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_interface_handle getIfaceHandle(interface_info *info) 361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde return (wifi_interface_handle)info; 381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg) 411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* TODO: check for multiple handlers? */ 45bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_lock(&info->cb_lock); 46bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 47bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->num_event_cb < info->alloc_event_cb) { 501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].nl_cmd = cmd; 511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].vendor_id = 0; 521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].vendor_subcmd = 0; 531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].cb_func = func; 541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].cb_arg = arg; 5568d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Successfully added event handler %p:%p for command %d at %d", 5668d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande arg, func, cmd, info->num_event_cb); 571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_event_cb++; 58bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande result = WIFI_SUCCESS; 591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 60bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 61bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_unlock(&info->cb_lock); 62bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande return result; 631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_register_vendor_handler(wifi_handle handle, 661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg) 671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde /* TODO: check for multiple handlers? */ 71bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_lock(&info->cb_lock); 72bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 73bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->num_event_cb < info->alloc_event_cb) { 761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].nl_cmd = NL80211_CMD_VENDOR; 771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].vendor_id = id; 781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].vendor_subcmd = subcmd; 791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].cb_func = func; 801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->event_cb[info->num_event_cb].cb_arg = arg; 8168d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d", 8268d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande arg, func, id, subcmd, info->num_event_cb); 831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_event_cb++; 84bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande result = WIFI_SUCCESS; 851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 86bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 87bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_unlock(&info->cb_lock); 88bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande return result; 891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_unregister_handler(wifi_handle handle, int cmd) 921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (cmd == NL80211_CMD_VENDOR) { 961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers"); 97bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande return; 981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 100bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_lock(&info->cb_lock); 101bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < info->num_event_cb; i++) { 1031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->event_cb[i].nl_cmd == cmd) { 10468d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d", 10568d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i); 10628237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande 1071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memmove(&info->event_cb[i], &info->event_cb[i+1], 108082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande (info->num_event_cb - i - 1) * sizeof(cb_info)); 1091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_event_cb--; 110bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande break; 1111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 113bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 114bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_unlock(&info->cb_lock); 1151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd) 1181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 1201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 121bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_lock(&info->cb_lock); 122bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 1231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < info->num_event_cb; i++) { 1241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR 1261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde && info->event_cb[i].vendor_id == id 1271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde && info->event_cb[i].vendor_subcmd == subcmd) { 12868d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d", 12968d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i); 1301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memmove(&info->event_cb[i], &info->event_cb[i+1], 131082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande (info->num_event_cb - i - 1) * sizeof(cb_info)); 1321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_event_cb--; 133bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande break; 1341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 136bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 137bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande pthread_mutex_unlock(&info->cb_lock); 1381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd) 1421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 1441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("registering command %d", id); 1461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 147bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande wifi_error result = WIFI_ERROR_OUT_OF_MEMORY; 148bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 1491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->num_cmd < info->alloc_cmd) { 1501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->cmd[info->num_cmd].id = id; 1511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->cmd[info->num_cmd].cmd = cmd; 15268d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd); 1531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_cmd++; 154bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande result = WIFI_SUCCESS; 1551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 156bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 157bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande return result; 1581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1601a526434ae215b48970501ccb463d4e77af39c9eVinit DeshapndeWifiCommand *wifi_unregister_cmd(wifi_handle handle, int id) 1611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 1631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 1641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde ALOGD("un-registering command %d", id); 1651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 166bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande WifiCommand *cmd = NULL; 167bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande 1681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < info->num_cmd; i++) { 1691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->cmd[i].id == id) { 170bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande cmd = info->cmd[i].cmd; 1711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); 1721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_cmd--; 17368d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); 174bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande break; 1751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 1771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 178bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande return cmd; 1791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 1801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 181115bcffc16c53e9552c09a6792666c52a633b4f2AshwinWifiCommand *wifi_get_cmd(wifi_handle handle, int id) 182115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin{ 183115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin hal_info *info = (hal_info *)handle; 184115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin 185115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin WifiCommand *cmd = NULL; 186115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin 187115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin for (int i = 0; i < info->num_cmd; i++) { 188115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin if (info->cmd[i].id == id) { 189115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin cmd = info->cmd[i].cmd; 190115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin break; 191115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin } 192115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin } 193115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin 194115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin return cmd; 195115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin} 196115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin 1971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd) 1981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{ 1991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde hal_info *info = (hal_info *)handle; 2001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde 2011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde for (int i = 0; i < info->num_cmd; i++) { 2021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde if (info->cmd[i].cmd == cmd) { 2031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde int id = info->cmd[i].id; 2041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info)); 2051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde info->num_cmd--; 206082cb621b1dd1ad150a747d5010fed0888ae416cVinit Deshpande ALOGI("Successfully removed command %d: %p from %d", id, cmd, i); 207bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande break; 2081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde } 2101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde} 211