Merge KeystoneQ-ww-20190522
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / cpp_bindings.h
diff --git a/cpp_bindings.h b/cpp_bindings.h
new file mode 100755 (executable)
index 0000000..d1e1e5a
--- /dev/null
@@ -0,0 +1,347 @@
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "sync.h"
+
+class WifiEvent
+{
+    /* TODO: remove this when nl headers are updated */
+    static const unsigned NL80211_ATTR_MAX_INTERNAL = 256;
+private:
+    struct nl_msg *mMsg;
+    struct genlmsghdr *mHeader;
+    struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1];
+
+public:
+    WifiEvent(nl_msg *msg) {
+        mMsg = msg;
+        mHeader = NULL;
+        memset(mAttributes, 0, sizeof(mAttributes));
+    }
+    ~WifiEvent() {
+        /* don't destroy mMsg; it doesn't belong to us */
+    }
+
+    void log();
+
+    int parse();
+
+    genlmsghdr *header() {
+        return mHeader;
+    }
+
+    int get_cmd() {
+        return mHeader->cmd;
+    }
+
+    int get_vendor_id() {
+        return get_u32(NL80211_ATTR_VENDOR_ID);
+    }
+
+    int get_vendor_subcmd() {
+        return get_u32(NL80211_ATTR_VENDOR_SUBCMD);
+    }
+
+    void *get_vendor_data() {
+        return get_data(NL80211_ATTR_VENDOR_DATA);
+    }
+
+    int get_vendor_data_len() {
+        return get_len(NL80211_ATTR_VENDOR_DATA);
+    }
+
+    const char *get_cmdString();
+
+    nlattr ** attributes() {
+        return mAttributes;
+    }
+
+    nlattr *get_attribute(int attribute) {
+        return mAttributes[attribute];
+    }
+
+    uint8_t get_u8(int attribute) {
+        return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0;
+    }
+
+    uint16_t get_u16(int attribute) {
+        return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0;
+    }
+
+    uint32_t get_u32(int attribute) {
+        return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0;
+    }
+
+    uint64_t get_u64(int attribute) {
+        return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0;
+    }
+
+    int get_len(int attribute) {
+        return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0;
+    }
+
+    void *get_data(int attribute) {
+        return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
+    }
+
+private:
+    WifiEvent(const WifiEvent&);        // hide copy constructor to prevent copies
+};
+
+class nl_iterator {
+    struct nlattr *pos;
+    int rem;
+public:
+    nl_iterator(struct nlattr *attr) {
+        pos = (struct nlattr *)nla_data(attr);
+        rem = nla_len(attr);
+    }
+    bool has_next() {
+        return nla_ok(pos, rem);
+    }
+    void next() {
+        pos = (struct nlattr *)nla_next(pos, &(rem));
+    }
+    struct nlattr *get() {
+        return pos;
+    }
+    uint16_t get_type() {
+        return pos->nla_type;
+    }
+    uint8_t get_u8() {
+        return nla_get_u8(pos);
+    }
+    uint16_t get_u16() {
+        return nla_get_u16(pos);
+    }
+    uint32_t get_u32() {
+        return nla_get_u32(pos);
+    }
+    uint64_t get_u64() {
+        return nla_get_u64(pos);
+    }
+    void* get_data() {
+        return nla_data(pos);
+    }
+    int get_len() {
+        return nla_len(pos);
+    }
+private:
+    nl_iterator(const nl_iterator&);    // hide copy constructor to prevent copies
+};
+
+class WifiRequest
+{
+private:
+    int mFamily;
+    int mIface;
+    struct nl_msg *mMsg;
+
+public:
+    WifiRequest(int family) {
+        mMsg = NULL;
+        mFamily = family;
+        mIface = -1;
+    }
+
+    WifiRequest(int family, int iface) {
+        mMsg = NULL;
+        mFamily = family;
+        mIface = iface;
+    }
+
+    ~WifiRequest() {
+        destroy();
+    }
+
+    void destroy() {
+        if (mMsg) {
+            nlmsg_free(mMsg);
+            mMsg = NULL;
+        }
+    }
+
+    nl_msg *getMessage() {
+        return mMsg;
+    }
+
+    /* Command assembly helpers */
+    int create(int family, uint8_t cmd, int flags, int hdrlen);
+    int create(uint8_t cmd) {
+        return create(mFamily, cmd, 0, 0);
+    }
+
+    int create(uint32_t id, int subcmd);
+
+    int put(int attribute, void *ptr, unsigned len) {
+        return nla_put(mMsg, attribute, len, ptr);
+    }
+    int put_u8(int attribute, uint8_t value) {
+        return nla_put(mMsg, attribute, sizeof(value), &value);
+    }
+    int put_u16(int attribute, uint16_t value) {
+        return nla_put(mMsg, attribute, sizeof(value), &value);
+    }
+    int put_u32(int attribute, uint32_t value) {
+        return nla_put(mMsg, attribute, sizeof(value), &value);
+    }
+    int put_u64(int attribute, uint64_t value) {
+        return nla_put(mMsg, attribute, sizeof(value), &value);
+    }
+    int put_string(int attribute, const char *value) {
+        return nla_put(mMsg, attribute, strlen(value) + 1, value);
+    }
+    int put_addr(int attribute, mac_addr value) {
+        return nla_put(mMsg, attribute, sizeof(mac_addr), value);
+    }
+
+    struct nlattr * attr_start(int attribute) {
+        return nla_nest_start(mMsg, attribute);
+    }
+    void attr_end(struct nlattr *attr) {
+        nla_nest_end(mMsg, attr);
+    }
+
+    int set_iface_id(int ifindex) {
+        return put_u32(NL80211_ATTR_IFINDEX, ifindex);
+    }
+private:
+    WifiRequest(const WifiRequest&);        // hide copy constructor to prevent copies
+
+};
+
+class WifiCommand
+{
+protected:
+    hal_info *mInfo;
+    WifiRequest mMsg;
+    Condition mCondition;
+    wifi_request_id mId;
+    interface_info *mIfaceInfo;
+    int mRefs;
+public:
+    WifiCommand(wifi_handle handle, wifi_request_id id)
+            : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1)
+    {
+        mIfaceInfo = NULL;
+        mInfo = getHalInfo(handle);
+        // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
+    }
+
+    WifiCommand(wifi_interface_handle iface, wifi_request_id id)
+            : mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), mId(id), mRefs(1)
+    {
+        mIfaceInfo = getIfaceInfo(iface);
+        mInfo = getHalInfo(iface);
+        // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
+    }
+
+    virtual ~WifiCommand() {
+        // ALOGD("WifiCommand %p destroyed", this);
+    }
+
+    wifi_request_id id() {
+        return mId;
+    }
+
+    virtual void addRef() {
+        __sync_add_and_fetch(&mRefs, 1);
+        //int refs = __sync_add_and_fetch(&mRefs, 1);
+        // ALOGD("addRef: WifiCommand %p has %d references", this, refs);
+    }
+
+    virtual void releaseRef() {
+        int refs = __sync_sub_and_fetch(&mRefs, 1);
+        if (refs == 0) {
+            delete this;
+        } else {
+            // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs);
+        }
+    }
+
+    virtual int create() {
+        /* by default there is no way to cancel */
+        //ALOGD("WifiCommand %p can't be created", this);
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+
+    virtual int cancel() {
+        /* by default there is no way to cancel */
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+
+    int requestResponse();
+    int requestEvent(int cmd);
+    int requestVendorEvent(uint32_t id, int subcmd);
+    int requestResponse(WifiRequest& request);
+
+protected:
+    wifi_handle wifiHandle() {
+        return getWifiHandle(mInfo);
+    }
+
+    wifi_interface_handle ifaceHandle() {
+        return getIfaceHandle(mIfaceInfo);
+    }
+
+    int familyId() {
+        return mInfo->nl80211_family_id;
+    }
+
+    int ifaceId() {
+        return mIfaceInfo->id;
+    }
+
+    /* Override this method to parse reply and dig out data; save it in the object */
+    virtual int handleResponse(WifiEvent& reply) {
+        ALOGI("skipping a response");
+        return NL_SKIP;
+    }
+
+    /* Override this method to parse event and dig out data; save it in the object */
+    virtual int handleEvent(WifiEvent& event) {
+        ALOGI("skipping an event");
+        return NL_SKIP;
+    }
+
+    int registerHandler(int cmd) {
+        return wifi_register_handler(wifiHandle(), cmd, &event_handler, this);
+    }
+
+    void unregisterHandler(int cmd) {
+        wifi_unregister_handler(wifiHandle(), cmd);
+    }
+
+    int registerVendorHandler(uint32_t id, int subcmd) {
+        return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
+    }
+
+    void unregisterVendorHandler(uint32_t id, int subcmd) {
+        wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
+    }
+
+private:
+    WifiCommand(const WifiCommand& );           // hide copy constructor to prevent copies
+
+    /* Event handling */
+    static int response_handler(struct nl_msg *msg, void *arg);
+
+    static int event_handler(struct nl_msg *msg, void *arg);
+
+    /* Other event handlers */
+    static int valid_handler(struct nl_msg *msg, void *arg);
+
+    static int ack_handler(struct nl_msg *msg, void *arg);
+
+    static int finish_handler(struct nl_msg *msg, void *arg);
+
+    static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
+};
+
+/* nl message processing macros (required to pass C++ type checks) */
+
+#define for_each_attr(pos, nla, rem) \
+    for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \
+        nla_ok(pos, rem); \
+        pos = (nlattr *)nla_next(pos, &(rem)))
+