diff options
author | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2021-09-08 15:50:29 +0200 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2021-09-08 15:50:29 +0200 |
commit | 52f5d170b4f892d12f3843431f468827e16efeb8 (patch) | |
tree | 42176b596c0ceb455065f511808c810bdcb6a21a /wifi_hal/cpp_bindings.cpp | |
parent | e4666454d2c3d5b1a54a3ba27d98a53ef5a79da5 (diff) | |
download | hardware_replicant_wlan-52f5d170b4f892d12f3843431f468827e16efeb8.tar.gz hardware_replicant_wlan-52f5d170b4f892d12f3843431f468827e16efeb8.tar.bz2 hardware_replicant_wlan-52f5d170b4f892d12f3843431f468827e16efeb8.zip |
Move everything out of the bcmdhd directory
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
Diffstat (limited to 'wifi_hal/cpp_bindings.cpp')
-rwxr-xr-x | wifi_hal/cpp_bindings.cpp | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/wifi_hal/cpp_bindings.cpp b/wifi_hal/cpp_bindings.cpp new file mode 100755 index 0000000..5ca6431 --- /dev/null +++ b/wifi_hal/cpp_bindings.cpp @@ -0,0 +1,763 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Portions copyright (C) 2017 Broadcom Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#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 <ctype.h> +#include <errno.h> + +#include "wifi_hal.h" +#include "common.h" +#include "cpp_bindings.h" + +pthread_mutex_t ResponseMutex; +void InitResponseLock() { + pthread_mutex_init(&ResponseMutex, NULL); +} + +void DestroyResponseLock() +{ + pthread_mutex_destroy(&ResponseMutex); +} + +void appendFmt(char *buf, int &offset, const char *fmt, ...) +{ + va_list params; + va_start(params, fmt); + offset += vsprintf(buf + offset, fmt, params); + va_end(params); +} + +#define C2S(x) case x: return #x; + +static const char *cmdToString(int cmd) +{ + switch (cmd) { + C2S(NL80211_CMD_UNSPEC) + C2S(NL80211_CMD_GET_WIPHY) + C2S(NL80211_CMD_SET_WIPHY) + C2S(NL80211_CMD_NEW_WIPHY) + C2S(NL80211_CMD_DEL_WIPHY) + C2S(NL80211_CMD_GET_INTERFACE) + C2S(NL80211_CMD_SET_INTERFACE) + C2S(NL80211_CMD_NEW_INTERFACE) + C2S(NL80211_CMD_DEL_INTERFACE) + C2S(NL80211_CMD_GET_KEY) + C2S(NL80211_CMD_SET_KEY) + C2S(NL80211_CMD_NEW_KEY) + C2S(NL80211_CMD_DEL_KEY) + C2S(NL80211_CMD_GET_BEACON) + C2S(NL80211_CMD_SET_BEACON) + C2S(NL80211_CMD_START_AP) + C2S(NL80211_CMD_STOP_AP) + C2S(NL80211_CMD_GET_STATION) + C2S(NL80211_CMD_SET_STATION) + C2S(NL80211_CMD_NEW_STATION) + C2S(NL80211_CMD_DEL_STATION) + C2S(NL80211_CMD_GET_MPATH) + C2S(NL80211_CMD_SET_MPATH) + C2S(NL80211_CMD_NEW_MPATH) + C2S(NL80211_CMD_DEL_MPATH) + C2S(NL80211_CMD_SET_BSS) + C2S(NL80211_CMD_SET_REG) + C2S(NL80211_CMD_REQ_SET_REG) + C2S(NL80211_CMD_GET_MESH_CONFIG) + C2S(NL80211_CMD_SET_MESH_CONFIG) + C2S(NL80211_CMD_SET_MGMT_EXTRA_IE) + C2S(NL80211_CMD_GET_REG) + C2S(NL80211_CMD_GET_SCAN) + C2S(NL80211_CMD_TRIGGER_SCAN) + C2S(NL80211_CMD_NEW_SCAN_RESULTS) + C2S(NL80211_CMD_SCAN_ABORTED) + C2S(NL80211_CMD_REG_CHANGE) + C2S(NL80211_CMD_AUTHENTICATE) + C2S(NL80211_CMD_ASSOCIATE) + C2S(NL80211_CMD_DEAUTHENTICATE) + C2S(NL80211_CMD_DISASSOCIATE) + C2S(NL80211_CMD_MICHAEL_MIC_FAILURE) + C2S(NL80211_CMD_REG_BEACON_HINT) + C2S(NL80211_CMD_JOIN_IBSS) + C2S(NL80211_CMD_LEAVE_IBSS) + C2S(NL80211_CMD_TESTMODE) + C2S(NL80211_CMD_CONNECT) + C2S(NL80211_CMD_ROAM) + C2S(NL80211_CMD_DISCONNECT) + C2S(NL80211_CMD_SET_WIPHY_NETNS) + C2S(NL80211_CMD_GET_SURVEY) + C2S(NL80211_CMD_NEW_SURVEY_RESULTS) + C2S(NL80211_CMD_SET_PMKSA) + C2S(NL80211_CMD_DEL_PMKSA) + C2S(NL80211_CMD_FLUSH_PMKSA) + C2S(NL80211_CMD_REMAIN_ON_CHANNEL) + C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL) + C2S(NL80211_CMD_SET_TX_BITRATE_MASK) + C2S(NL80211_CMD_REGISTER_FRAME) + C2S(NL80211_CMD_FRAME) + C2S(NL80211_CMD_FRAME_TX_STATUS) + C2S(NL80211_CMD_SET_POWER_SAVE) + C2S(NL80211_CMD_GET_POWER_SAVE) + C2S(NL80211_CMD_SET_CQM) + C2S(NL80211_CMD_NOTIFY_CQM) + C2S(NL80211_CMD_SET_CHANNEL) + C2S(NL80211_CMD_SET_WDS_PEER) + C2S(NL80211_CMD_FRAME_WAIT_CANCEL) + C2S(NL80211_CMD_JOIN_MESH) + C2S(NL80211_CMD_LEAVE_MESH) + C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE) + C2S(NL80211_CMD_UNPROT_DISASSOCIATE) + C2S(NL80211_CMD_NEW_PEER_CANDIDATE) + C2S(NL80211_CMD_GET_WOWLAN) + C2S(NL80211_CMD_SET_WOWLAN) + C2S(NL80211_CMD_START_SCHED_SCAN) + C2S(NL80211_CMD_STOP_SCHED_SCAN) + C2S(NL80211_CMD_SCHED_SCAN_RESULTS) + C2S(NL80211_CMD_SCHED_SCAN_STOPPED) + C2S(NL80211_CMD_SET_REKEY_OFFLOAD) + C2S(NL80211_CMD_PMKSA_CANDIDATE) + C2S(NL80211_CMD_TDLS_OPER) + C2S(NL80211_CMD_TDLS_MGMT) + C2S(NL80211_CMD_UNEXPECTED_FRAME) + C2S(NL80211_CMD_PROBE_CLIENT) + C2S(NL80211_CMD_REGISTER_BEACONS) + C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME) + C2S(NL80211_CMD_SET_NOACK_MAP) + C2S(NL80211_CMD_CH_SWITCH_NOTIFY) + C2S(NL80211_CMD_START_P2P_DEVICE) + C2S(NL80211_CMD_STOP_P2P_DEVICE) + C2S(NL80211_CMD_CONN_FAILED) + C2S(NL80211_CMD_SET_MCAST_RATE) + C2S(NL80211_CMD_SET_MAC_ACL) + C2S(NL80211_CMD_RADAR_DETECT) + C2S(NL80211_CMD_GET_PROTOCOL_FEATURES) + C2S(NL80211_CMD_UPDATE_FT_IES) + C2S(NL80211_CMD_FT_EVENT) + C2S(NL80211_CMD_CRIT_PROTOCOL_START) + C2S(NL80211_CMD_CRIT_PROTOCOL_STOP) + C2S(NL80211_CMD_GET_COALESCE) + C2S(NL80211_CMD_SET_COALESCE) + C2S(NL80211_CMD_CHANNEL_SWITCH) + C2S(NL80211_CMD_VENDOR) + C2S(NL80211_CMD_SET_QOS_MAP) + default: + return "NL80211_CMD_UNKNOWN"; + } +} + +const char *attributeToString(int attribute) +{ + switch (attribute) { + C2S(NL80211_ATTR_UNSPEC) + + C2S(NL80211_ATTR_WIPHY) + C2S(NL80211_ATTR_WIPHY_NAME) + + C2S(NL80211_ATTR_IFINDEX) + C2S(NL80211_ATTR_IFNAME) + C2S(NL80211_ATTR_IFTYPE) + + C2S(NL80211_ATTR_MAC) + + C2S(NL80211_ATTR_KEY_DATA) + C2S(NL80211_ATTR_KEY_IDX) + C2S(NL80211_ATTR_KEY_CIPHER) + C2S(NL80211_ATTR_KEY_SEQ) + C2S(NL80211_ATTR_KEY_DEFAULT) + + C2S(NL80211_ATTR_BEACON_INTERVAL) + C2S(NL80211_ATTR_DTIM_PERIOD) + C2S(NL80211_ATTR_BEACON_HEAD) + C2S(NL80211_ATTR_BEACON_TAIL) + + C2S(NL80211_ATTR_STA_AID) + C2S(NL80211_ATTR_STA_FLAGS) + C2S(NL80211_ATTR_STA_LISTEN_INTERVAL) + C2S(NL80211_ATTR_STA_SUPPORTED_RATES) + C2S(NL80211_ATTR_STA_VLAN) + C2S(NL80211_ATTR_STA_INFO) + + C2S(NL80211_ATTR_WIPHY_BANDS) + + C2S(NL80211_ATTR_MNTR_FLAGS) + + C2S(NL80211_ATTR_MESH_ID) + C2S(NL80211_ATTR_STA_PLINK_ACTION) + C2S(NL80211_ATTR_MPATH_NEXT_HOP) + C2S(NL80211_ATTR_MPATH_INFO) + + C2S(NL80211_ATTR_BSS_CTS_PROT) + C2S(NL80211_ATTR_BSS_SHORT_PREAMBLE) + C2S(NL80211_ATTR_BSS_SHORT_SLOT_TIME) + + C2S(NL80211_ATTR_HT_CAPABILITY) + + C2S(NL80211_ATTR_SUPPORTED_IFTYPES) + + C2S(NL80211_ATTR_REG_ALPHA2) + C2S(NL80211_ATTR_REG_RULES) + + C2S(NL80211_ATTR_MESH_CONFIG) + + C2S(NL80211_ATTR_BSS_BASIC_RATES) + + C2S(NL80211_ATTR_WIPHY_TXQ_PARAMS) + C2S(NL80211_ATTR_WIPHY_FREQ) + C2S(NL80211_ATTR_WIPHY_CHANNEL_TYPE) + + C2S(NL80211_ATTR_KEY_DEFAULT_MGMT) + + C2S(NL80211_ATTR_MGMT_SUBTYPE) + C2S(NL80211_ATTR_IE) + + C2S(NL80211_ATTR_MAX_NUM_SCAN_SSIDS) + + C2S(NL80211_ATTR_SCAN_FREQUENCIES) + C2S(NL80211_ATTR_SCAN_SSIDS) + C2S(NL80211_ATTR_GENERATION) /* replaces old SCAN_GENERATION */ + C2S(NL80211_ATTR_BSS) + + C2S(NL80211_ATTR_REG_INITIATOR) + C2S(NL80211_ATTR_REG_TYPE) + + C2S(NL80211_ATTR_SUPPORTED_COMMANDS) + + C2S(NL80211_ATTR_FRAME) + C2S(NL80211_ATTR_SSID) + C2S(NL80211_ATTR_AUTH_TYPE) + C2S(NL80211_ATTR_REASON_CODE) + + C2S(NL80211_ATTR_KEY_TYPE) + + C2S(NL80211_ATTR_MAX_SCAN_IE_LEN) + C2S(NL80211_ATTR_CIPHER_SUITES) + + C2S(NL80211_ATTR_FREQ_BEFORE) + C2S(NL80211_ATTR_FREQ_AFTER) + + C2S(NL80211_ATTR_FREQ_FIXED) + + + C2S(NL80211_ATTR_WIPHY_RETRY_SHORT) + C2S(NL80211_ATTR_WIPHY_RETRY_LONG) + C2S(NL80211_ATTR_WIPHY_FRAG_THRESHOLD) + C2S(NL80211_ATTR_WIPHY_RTS_THRESHOLD) + + C2S(NL80211_ATTR_TIMED_OUT) + + C2S(NL80211_ATTR_USE_MFP) + + C2S(NL80211_ATTR_STA_FLAGS2) + + C2S(NL80211_ATTR_CONTROL_PORT) + + C2S(NL80211_ATTR_TESTDATA) + + C2S(NL80211_ATTR_PRIVACY) + + C2S(NL80211_ATTR_DISCONNECTED_BY_AP) + C2S(NL80211_ATTR_STATUS_CODE) + + C2S(NL80211_ATTR_CIPHER_SUITES_PAIRWISE) + C2S(NL80211_ATTR_CIPHER_SUITE_GROUP) + C2S(NL80211_ATTR_WPA_VERSIONS) + C2S(NL80211_ATTR_AKM_SUITES) + + C2S(NL80211_ATTR_REQ_IE) + C2S(NL80211_ATTR_RESP_IE) + + C2S(NL80211_ATTR_PREV_BSSID) + + C2S(NL80211_ATTR_KEY) + C2S(NL80211_ATTR_KEYS) + + C2S(NL80211_ATTR_PID) + + C2S(NL80211_ATTR_4ADDR) + + C2S(NL80211_ATTR_SURVEY_INFO) + + C2S(NL80211_ATTR_PMKID) + C2S(NL80211_ATTR_MAX_NUM_PMKIDS) + + C2S(NL80211_ATTR_DURATION) + + C2S(NL80211_ATTR_COOKIE) + + C2S(NL80211_ATTR_WIPHY_COVERAGE_CLASS) + + C2S(NL80211_ATTR_TX_RATES) + + C2S(NL80211_ATTR_FRAME_MATCH) + + C2S(NL80211_ATTR_ACK) + + C2S(NL80211_ATTR_PS_STATE) + + C2S(NL80211_ATTR_CQM) + + C2S(NL80211_ATTR_LOCAL_STATE_CHANGE) + + C2S(NL80211_ATTR_AP_ISOLATE) + + C2S(NL80211_ATTR_WIPHY_TX_POWER_SETTING) + C2S(NL80211_ATTR_WIPHY_TX_POWER_LEVEL) + + C2S(NL80211_ATTR_TX_FRAME_TYPES) + C2S(NL80211_ATTR_RX_FRAME_TYPES) + C2S(NL80211_ATTR_FRAME_TYPE) + + C2S(NL80211_ATTR_CONTROL_PORT_ETHERTYPE) + C2S(NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT) + + C2S(NL80211_ATTR_SUPPORT_IBSS_RSN) + + C2S(NL80211_ATTR_WIPHY_ANTENNA_TX) + C2S(NL80211_ATTR_WIPHY_ANTENNA_RX) + + C2S(NL80211_ATTR_MCAST_RATE) + + C2S(NL80211_ATTR_OFFCHANNEL_TX_OK) + + C2S(NL80211_ATTR_BSS_HT_OPMODE) + + C2S(NL80211_ATTR_KEY_DEFAULT_TYPES) + + C2S(NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION) + + C2S(NL80211_ATTR_MESH_SETUP) + + C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX) + C2S(NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX) + + C2S(NL80211_ATTR_SUPPORT_MESH_AUTH) + C2S(NL80211_ATTR_STA_PLINK_STATE) + + C2S(NL80211_ATTR_WOWLAN_TRIGGERS) + C2S(NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED) + + C2S(NL80211_ATTR_SCHED_SCAN_INTERVAL) + + C2S(NL80211_ATTR_INTERFACE_COMBINATIONS) + C2S(NL80211_ATTR_SOFTWARE_IFTYPES) + + C2S(NL80211_ATTR_REKEY_DATA) + + C2S(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS) + C2S(NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN) + + C2S(NL80211_ATTR_SCAN_SUPP_RATES) + + C2S(NL80211_ATTR_HIDDEN_SSID) + + C2S(NL80211_ATTR_IE_PROBE_RESP) + C2S(NL80211_ATTR_IE_ASSOC_RESP) + + C2S(NL80211_ATTR_STA_WME) + C2S(NL80211_ATTR_SUPPORT_AP_UAPSD) + + C2S(NL80211_ATTR_ROAM_SUPPORT) + + C2S(NL80211_ATTR_SCHED_SCAN_MATCH) + C2S(NL80211_ATTR_MAX_MATCH_SETS) + + C2S(NL80211_ATTR_PMKSA_CANDIDATE) + + C2S(NL80211_ATTR_TX_NO_CCK_RATE) + + C2S(NL80211_ATTR_TDLS_ACTION) + C2S(NL80211_ATTR_TDLS_DIALOG_TOKEN) + C2S(NL80211_ATTR_TDLS_OPERATION) + C2S(NL80211_ATTR_TDLS_SUPPORT) + C2S(NL80211_ATTR_TDLS_EXTERNAL_SETUP) + + C2S(NL80211_ATTR_DEVICE_AP_SME) + + C2S(NL80211_ATTR_DONT_WAIT_FOR_ACK) + + C2S(NL80211_ATTR_FEATURE_FLAGS) + + C2S(NL80211_ATTR_PROBE_RESP_OFFLOAD) + + C2S(NL80211_ATTR_PROBE_RESP) + + C2S(NL80211_ATTR_DFS_REGION) + + C2S(NL80211_ATTR_DISABLE_HT) + C2S(NL80211_ATTR_HT_CAPABILITY_MASK) + + C2S(NL80211_ATTR_NOACK_MAP) + + C2S(NL80211_ATTR_INACTIVITY_TIMEOUT) + + C2S(NL80211_ATTR_RX_SIGNAL_DBM) + + C2S(NL80211_ATTR_BG_SCAN_PERIOD) + + C2S(NL80211_ATTR_WDEV) + + C2S(NL80211_ATTR_USER_REG_HINT_TYPE) + + C2S(NL80211_ATTR_CONN_FAILED_REASON) + + C2S(NL80211_ATTR_SAE_DATA) + + C2S(NL80211_ATTR_VHT_CAPABILITY) + + C2S(NL80211_ATTR_SCAN_FLAGS) + + C2S(NL80211_ATTR_CHANNEL_WIDTH) + C2S(NL80211_ATTR_CENTER_FREQ1) + C2S(NL80211_ATTR_CENTER_FREQ2) + + C2S(NL80211_ATTR_P2P_CTWINDOW) + C2S(NL80211_ATTR_P2P_OPPPS) + + C2S(NL80211_ATTR_LOCAL_MESH_POWER_MODE) + + C2S(NL80211_ATTR_ACL_POLICY) + + C2S(NL80211_ATTR_MAC_ADDRS) + + C2S(NL80211_ATTR_MAC_ACL_MAX) + + C2S(NL80211_ATTR_RADAR_EVENT) + + C2S(NL80211_ATTR_EXT_CAPA) + C2S(NL80211_ATTR_EXT_CAPA_MASK) + + C2S(NL80211_ATTR_STA_CAPABILITY) + C2S(NL80211_ATTR_STA_EXT_CAPABILITY) + + C2S(NL80211_ATTR_PROTOCOL_FEATURES) + C2S(NL80211_ATTR_SPLIT_WIPHY_DUMP) + + C2S(NL80211_ATTR_DISABLE_VHT) + C2S(NL80211_ATTR_VHT_CAPABILITY_MASK) + + C2S(NL80211_ATTR_MDID) + C2S(NL80211_ATTR_IE_RIC) + + C2S(NL80211_ATTR_CRIT_PROT_ID) + C2S(NL80211_ATTR_MAX_CRIT_PROT_DURATION) + + C2S(NL80211_ATTR_PEER_AID) + + C2S(NL80211_ATTR_COALESCE_RULE) + + C2S(NL80211_ATTR_CH_SWITCH_COUNT) + C2S(NL80211_ATTR_CH_SWITCH_BLOCK_TX) + C2S(NL80211_ATTR_CSA_IES) + C2S(NL80211_ATTR_CSA_C_OFF_BEACON) + C2S(NL80211_ATTR_CSA_C_OFF_PRESP) + + C2S(NL80211_ATTR_RXMGMT_FLAGS) + + C2S(NL80211_ATTR_STA_SUPPORTED_CHANNELS) + + C2S(NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES) + + C2S(NL80211_ATTR_HANDLE_DFS) + + C2S(NL80211_ATTR_SUPPORT_5_MHZ) + C2S(NL80211_ATTR_SUPPORT_10_MHZ) + + C2S(NL80211_ATTR_OPMODE_NOTIF) + + C2S(NL80211_ATTR_VENDOR_ID) + C2S(NL80211_ATTR_VENDOR_SUBCMD) + C2S(NL80211_ATTR_VENDOR_DATA) + C2S(NL80211_ATTR_VENDOR_EVENTS) + + C2S(NL80211_ATTR_QOS_MAP) + default: + return "NL80211_ATTR_UNKNOWN"; + } +} + +void WifiEvent::log() { + parse(); + + byte *data = (byte *)genlmsg_attrdata(mHeader, 0); + int len = genlmsg_attrlen(mHeader, 0); + ALOGD("cmd = %s, len = %d", get_cmdString(), len); + ALOGD("vendor_id = %04x, vendor_subcmd = %d", get_vendor_id(), get_vendor_subcmd()); + + for (int i = 0; i < len; i += 16) { + char line[81]; + int linelen = min(16, len - i); + int offset = 0; + appendFmt(line, offset, "%02x", data[i]); + for (int j = 1; j < linelen; j++) { + appendFmt(line, offset, " %02x", data[i+j]); + } + + for (int j = linelen; j < 16; j++) { + appendFmt(line, offset, " "); + } + + line[23] = '-'; + + appendFmt(line, offset, " "); + + for (int j = 0; j < linelen; j++) { + if (isprint(data[i+j])) { + appendFmt(line, offset, "%c", data[i+j]); + } else { + appendFmt(line, offset, "-"); + } + } + + ALOGD("%s", line); + } + + for (unsigned i = 0; i < NL80211_ATTR_MAX_INTERNAL; i++) { + if (mAttributes[i] != NULL) { + ALOGD("found attribute %s", attributeToString(i)); + } + } + + ALOGD("-- End of message --"); +} + +const char *WifiEvent::get_cmdString() { + return cmdToString(get_cmd()); +} + + +int WifiEvent::parse() { + if (mHeader != NULL) { + return WIFI_SUCCESS; + } + mHeader = (genlmsghdr *)nlmsg_data(nlmsg_hdr(mMsg)); + int result = nla_parse(mAttributes, NL80211_ATTR_MAX_INTERNAL, genlmsg_attrdata(mHeader, 0), + genlmsg_attrlen(mHeader, 0), NULL); + + // ALOGD("event len = %d", nlmsg_hdr(mMsg)->nlmsg_len); + return result; +} + +int WifiRequest::create(int family, uint8_t cmd, int flags, int hdrlen) { + + destroy(); + + mMsg = nlmsg_alloc(); + if (mMsg != NULL) { + genlmsg_put(mMsg, /* pid = */ 0, /* seq = */ 0, family, + hdrlen, flags, cmd, /* version = */ 0); + return WIFI_SUCCESS; + } else { + return WIFI_ERROR_OUT_OF_MEMORY; + } +} + +int WifiRequest::create(uint32_t id, int subcmd) { + int res = create(NL80211_CMD_VENDOR); + if (res < 0) { + return res; + } + + res = put_u32(NL80211_ATTR_VENDOR_ID, id); + if (res < 0) { + return res; + } + + res = put_u32(NL80211_ATTR_VENDOR_SUBCMD, subcmd); + if (res < 0) { + return res; + } + + if (mIface != -1) { + res = set_iface_id(mIface); + } + + return res; +} + + +static int no_seq_check(struct nl_msg *msg, void *arg) +{ + return NL_OK; +} + +int WifiCommand::requestResponse() { + int err = create(); /* create the message */ + if (err < 0) { + return err; + } + + return requestResponse(mMsg); +} + +int WifiCommand::requestResponse(WifiRequest& request) { + pthread_mutex_lock(&ResponseMutex); + int err = 0, res = 0; + + struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + goto out; + + err = nl_send_auto_complete(mInfo->cmd_sock, request.getMessage()); /* send message */ + if (err < 0) + goto out; + + err = 1; + + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); + nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, response_handler, this); + + while (err > 0) { /* wait for reply */ + int res = nl_recvmsgs(mInfo->cmd_sock, cb); + if (res) { + ALOGE("nl80211: %s->nl_recvmsgs failed: %d", __func__, res); + } + } +out: + nl_cb_put(cb); + pthread_mutex_unlock(&ResponseMutex); + return err; +} + +int WifiCommand::requestEvent(int cmd) { + + ALOGD("requesting event %d", cmd); + + int res = wifi_register_handler(wifiHandle(), cmd, event_handler, this); + if (res < 0) { + return res; + } + + res = create(); /* create the message */ + if (res < 0) + goto out; + + ALOGD("waiting for response %d", cmd); + + res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ + if (res < 0) + goto out; + + ALOGD("waiting for event %d", cmd); + res = mCondition.wait(); + if (res < 0) + goto out; + +out: + wifi_unregister_handler(wifiHandle(), cmd); + return res; +} + +int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) { + + int res = wifi_register_vendor_handler(wifiHandle(), id, subcmd, event_handler, this); + if (res < 0) { + return res; + } + + res = create(); /* create the message */ + if (res < 0) + goto out; + + res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); /* send message */ + if (res < 0) + goto out; + + res = mCondition.wait(); + if (res < 0) + goto out; + +out: + wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); + return res; +} + +/* Event handlers */ +int WifiCommand::response_handler(struct nl_msg *msg, void *arg) { + // ALOGD("response_handler called"); + WifiCommand *cmd = (WifiCommand *)arg; + WifiEvent reply(msg); + int res = reply.parse(); + if (res < 0) { + ALOGE("Failed to parse reply message = %d", res); + return NL_SKIP; + } else { + // reply.log(); + return cmd->handleResponse(reply); + } +} + +int WifiCommand::event_handler(struct nl_msg *msg, void *arg) { + WifiCommand *cmd = (WifiCommand *)arg; + WifiEvent event(msg); + int res = event.parse(); + if (res < 0) { + ALOGE("Failed to parse event = %d", res); + res = NL_SKIP; + } else { + res = cmd->handleEvent(event); + } + + cmd->mCondition.signal(); + return res; +} + +/* Other event handlers */ +int WifiCommand::valid_handler(struct nl_msg *msg, void *arg) { + // ALOGD("valid_handler called"); + int *err = (int *)arg; + *err = 0; + return NL_SKIP; +} + +int WifiCommand::ack_handler(struct nl_msg *msg, void *arg) { + // ALOGD("ack_handler called"); + int *err = (int *)arg; + *err = 0; + return NL_STOP; +} + +int WifiCommand::finish_handler(struct nl_msg *msg, void *arg) { + // ALOGD("finish_handler called"); + int *ret = (int *)arg; + *ret = 0; + return NL_SKIP; +} + +int WifiCommand::error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { + int *ret = (int *)arg; + *ret = err->error; + + // ALOGD("error_handler received : %d", err->error); + return NL_SKIP; +} |