Merge KeystoneQ-ww-20190522
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / common.cpp
diff --git a/common.cpp b/common.cpp
new file mode 100755 (executable)
index 0000000..e0de0bc
--- /dev/null
@@ -0,0 +1,244 @@
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/handlers.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+
+interface_info *getIfaceInfo(wifi_interface_handle handle)
+{
+    return (interface_info *)handle;
+}
+
+wifi_handle getWifiHandle(wifi_interface_handle handle)
+{
+    return getIfaceInfo(handle)->handle;
+}
+
+hal_info *getHalInfo(wifi_handle handle)
+{
+    return (hal_info *)handle;
+}
+
+hal_info *getHalInfo(wifi_interface_handle handle)
+{
+    return getHalInfo(getWifiHandle(handle));
+}
+
+wifi_handle getWifiHandle(hal_info *info)
+{
+    return (wifi_handle)info;
+}
+
+wifi_interface_handle getIfaceHandle(interface_info *info)
+{
+    return (wifi_interface_handle)info;
+}
+
+wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
+{
+    hal_info *info = (hal_info *)handle;
+
+    /* TODO: check for multiple handlers? */
+    pthread_mutex_lock(&info->cb_lock);
+
+    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
+
+    if (info->num_event_cb < info->alloc_event_cb) {
+        info->event_cb[info->num_event_cb].nl_cmd  = cmd;
+        info->event_cb[info->num_event_cb].vendor_id  = 0;
+        info->event_cb[info->num_event_cb].vendor_subcmd  = 0;
+        info->event_cb[info->num_event_cb].cb_func = func;
+        info->event_cb[info->num_event_cb].cb_arg  = arg;
+        /*
+        ALOGI("Successfully added event handler %p:%p for command %d at %d",
+                arg, func, cmd, info->num_event_cb);*/
+        info->num_event_cb++;
+        result = WIFI_SUCCESS;
+    }
+
+    pthread_mutex_unlock(&info->cb_lock);
+    return result;
+}
+
+wifi_error wifi_register_vendor_handler(wifi_handle handle,
+        uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
+{
+    hal_info *info = (hal_info *)handle;
+
+//ALOGD("GSCAN register handle wifi_register_vendor_handler %p", handle);
+    /* TODO: check for multiple handlers? */
+    pthread_mutex_lock(&info->cb_lock);
+    //ALOGI("Added event handler %p", info);
+
+    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
+
+    //    ALOGD("register_vendor_handler: handle = %p", handle);
+    if (info->num_event_cb < info->alloc_event_cb) {
+        info->event_cb[info->num_event_cb].nl_cmd  = NL80211_CMD_VENDOR;
+        info->event_cb[info->num_event_cb].vendor_id  = id;
+        info->event_cb[info->num_event_cb].vendor_subcmd  = subcmd;
+        info->event_cb[info->num_event_cb].cb_func = func;
+        info->event_cb[info->num_event_cb].cb_arg  = arg;
+        /*
+        ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
+                arg, func, id, subcmd, info->num_event_cb);*/
+        info->num_event_cb++;
+        result = WIFI_SUCCESS;
+    }
+
+    pthread_mutex_unlock(&info->cb_lock);
+    return result;
+}
+
+void wifi_unregister_handler(wifi_handle handle, int cmd)
+{
+    hal_info *info = (hal_info *)handle;
+
+    if (cmd == NL80211_CMD_VENDOR) {
+        ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers");
+        return;
+    }
+
+    pthread_mutex_lock(&info->cb_lock);
+
+    for (int i = 0; i < info->num_event_cb; i++) {
+        if (info->event_cb[i].nl_cmd == cmd) {
+            /*
+            ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d",
+                    info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i);*/
+
+            memmove(&info->event_cb[i], &info->event_cb[i+1],
+                (info->num_event_cb - i - 1) * sizeof(cb_info));
+            info->num_event_cb--;
+            break;
+        }
+    }
+
+    pthread_mutex_unlock(&info->cb_lock);
+}
+
+void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
+{
+    hal_info *info = (hal_info *)handle;
+
+    pthread_mutex_lock(&info->cb_lock);
+
+    for (int i = 0; i < info->num_event_cb; i++) {
+
+        if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
+                && info->event_cb[i].vendor_id == id
+                && info->event_cb[i].vendor_subcmd == subcmd) {
+            /*
+            ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
+                    info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i);*/
+            memmove(&info->event_cb[i], &info->event_cb[i+1],
+                (info->num_event_cb - i - 1) * sizeof(cb_info));
+            info->num_event_cb--;
+            break;
+        }
+    }
+
+    pthread_mutex_unlock(&info->cb_lock);
+}
+
+
+wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
+{
+    hal_info *info = (hal_info *)handle;
+
+    //ALOGD("registering command %d", id);
+
+    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
+
+    if (info->num_cmd < info->alloc_cmd) {
+        info->cmd[info->num_cmd].id   = id;
+        info->cmd[info->num_cmd].cmd  = cmd;
+        //ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd);
+        info->num_cmd++;
+        result = WIFI_SUCCESS;
+    }
+
+    return result;
+}
+
+WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id)
+{
+    hal_info *info = (hal_info *)handle;
+
+    //ALOGD("un-registering command %d", id);
+
+    WifiCommand *cmd = NULL;
+
+    for (int i = 0; i < info->num_cmd; i++) {
+        if (info->cmd[i].id == id) {
+            cmd = info->cmd[i].cmd;
+            memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
+            info->num_cmd--;
+            //ALOGI("Successfully removed command %d: %p from %d", id, cmd, i);
+            break;
+        }
+    }
+
+    return cmd;
+}
+
+WifiCommand *wifi_get_cmd(wifi_handle handle, int id)
+{
+    hal_info *info = (hal_info *)handle;
+
+    WifiCommand *cmd = NULL;
+
+    for (int i = 0; i < info->num_cmd; i++) {
+        if (info->cmd[i].id == id) {
+            cmd = info->cmd[i].cmd;
+            break;
+        }
+    }
+
+    return cmd;
+}
+
+void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd)
+{
+    hal_info *info = (hal_info *)handle;
+
+    for (int i = 0; i < info->num_cmd; i++) {
+        if (info->cmd[i].cmd == cmd) {
+            memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
+            info->num_cmd--;
+            //ALOGI("Successfully removed command %d: %p from %d", id, cmd, i);
+            break;
+        }
+    }
+}
+
+wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
+{
+       wifi_handle handle = getWifiHandle(iface);
+
+       WifiCommand *cmd = wifi_unregister_cmd(handle, id);
+       //ALOGD("Cancel WifiCommand = %p", cmd);
+       if (cmd) {
+               cmd->cancel();
+               cmd->releaseRef();
+               return WIFI_SUCCESS;
+       }
+
+    return WIFI_ERROR_INVALID_ARGS;
+}