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