/* * Copyright (C) 2014 The Android Open Source Project * * 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. */ #ifndef __WIFI_HAL_CPP_BINDINGS_H__ #define __WIFI_HAL_CPP_BINDINGS_H__ #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, int flags, int hdrlen) { return create(mFamily, cmd, flags, hdrlen); } int create(uint8_t cmd) { return create(mFamily, cmd, 0, 0); } int create(uint32_t id, int subcmd); 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_s8(int attribute, s8 value) { return nla_put(mMsg, attribute, sizeof(int8_t), &value); } int put_s16(int attribute, s16 value) { return nla_put(mMsg, attribute, sizeof(int16_t), &value); } int put_s32(int attribute, s32 value) { return nla_put(mMsg, attribute, sizeof(int32_t), &value); } int put_s64(int attribute, s64 value) { return nla_put(mMsg, attribute, sizeof(int64_t), &value); } u8 get_u8(const struct nlattr *nla) { return *(u8 *) nla_data(nla); } u16 get_u16(const struct nlattr *nla) { return *(u16 *) nla_data(nla); } u32 get_u32(const struct nlattr *nla) { return *(u32 *) nla_data(nla); } u64 get_u64(const struct nlattr *nla) { return *(u64 *) nla_data(nla); } s8 get_s8(const struct nlattr *nla) { return *(s8 *) nla_data(nla); } s16 get_s16(const struct nlattr *nla) { return *(s16 *) nla_data(nla); } s32 get_s32(const struct nlattr *nla) { return *(s32 *) nla_data(nla); } s64 get_s64(const struct nlattr *nla) { return *(s64 *) nla_data(nla); } 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); } int put_bytes(int attribute, const char *data, int len) { return nla_put(mMsg, attribute, len, data); } 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; public: WifiCommand(wifi_handle handle, wifi_request_id id) : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id) { 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) { 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 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); }; //WifiVendorCommand class class WifiVendorCommand: public WifiCommand { protected: u32 mVendor_id; u32 mSubcmd; char *mVendorData; u32 mDataLen; public: WifiVendorCommand(wifi_handle handle, wifi_request_id id, u32 vendor_id, u32 subcmd); virtual ~WifiVendorCommand(); virtual int create(); virtual int requestResponse(); virtual int requestEvent(); virtual int put_u8(int attribute, uint8_t value); virtual int put_u16(int attribute, uint16_t value); virtual int put_u32(int attribute, uint32_t value); virtual int put_u64(int attribute, uint64_t value); virtual int put_s8(int attribute, s8 value); virtual int put_s16(int attribute, s16 value); virtual int put_s32(int attribute, s32 value); virtual int put_s64(int attribute, s64 value); virtual u8 get_u8(const struct nlattr *nla); virtual u16 get_u16(const struct nlattr *nla); virtual u32 get_u32(const struct nlattr *nla); virtual u64 get_u64(const struct nlattr *nla); virtual s8 get_s8(const struct nlattr *nla); virtual s16 get_s16(const struct nlattr *nla); virtual s32 get_s32(const struct nlattr *nla); virtual s64 get_s64(const struct nlattr *nla); virtual int put_string(int attribute, const char *value); virtual int put_addr(int attribute, mac_addr value); virtual struct nlattr * attr_start(int attribute); virtual void attr_end(struct nlattr *attribute); virtual int set_iface_id(const char* name); virtual int put_bytes(int attribute, const char *data, int len); virtual wifi_error get_mac_addr(struct nlattr **tb_vendor, int attribute, mac_addr addr); protected: /* Override this method to parse reply and dig out data; save it in the corresponding object */ virtual int handleResponse(WifiEvent &reply); /* Override this method to parse event and dig out data; save it in the object */ virtual int handleEvent(WifiEvent &event); }; /* 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))) wifi_error initialize_vendor_cmd(wifi_interface_handle iface, wifi_request_id id, u32 subcmd, WifiVendorCommand **vCommand); #endif