1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Portions copyright (C) 2017 Broadcom Limited 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <hardware_legacy/wifi_hal.h> 20 #include "common.h" 21 #include "sync.h" 22 23 class WifiEvent 24 { 25 /* TODO: remove this when nl headers are updated */ 26 static const unsigned NL80211_ATTR_MAX_INTERNAL = 256; 27 private: 28 struct nl_msg *mMsg; 29 struct genlmsghdr *mHeader; 30 struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1]; 31 32 public: WifiEvent(nl_msg * msg)33 WifiEvent(nl_msg *msg) { 34 mMsg = msg; 35 mHeader = NULL; 36 memset(mAttributes, 0, sizeof(mAttributes)); 37 } ~WifiEvent()38 ~WifiEvent() { 39 /* don't destroy mMsg; it doesn't belong to us */ 40 } 41 42 void log(); 43 44 int parse(); 45 header()46 genlmsghdr *header() { 47 return mHeader; 48 } 49 get_cmd()50 int get_cmd() { 51 return mHeader->cmd; 52 } 53 get_vendor_id()54 int get_vendor_id() { 55 return get_u32(NL80211_ATTR_VENDOR_ID); 56 } 57 get_vendor_subcmd()58 int get_vendor_subcmd() { 59 return get_u32(NL80211_ATTR_VENDOR_SUBCMD); 60 } 61 get_vendor_data()62 void *get_vendor_data() { 63 return get_data(NL80211_ATTR_VENDOR_DATA); 64 } 65 get_vendor_data_len()66 int get_vendor_data_len() { 67 return get_len(NL80211_ATTR_VENDOR_DATA); 68 } 69 70 const char *get_cmdString(); 71 attributes()72 nlattr ** attributes() { 73 return mAttributes; 74 } 75 get_attribute(int attribute)76 nlattr *get_attribute(int attribute) { 77 return mAttributes[attribute]; 78 } 79 get_u8(int attribute)80 uint8_t get_u8(int attribute) { 81 return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0; 82 } 83 get_u16(int attribute)84 uint16_t get_u16(int attribute) { 85 return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0; 86 } 87 get_u32(int attribute)88 uint32_t get_u32(int attribute) { 89 return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0; 90 } 91 get_u64(int attribute)92 uint64_t get_u64(int attribute) { 93 return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0; 94 } 95 get_len(int attribute)96 int get_len(int attribute) { 97 return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0; 98 } 99 get_data(int attribute)100 void *get_data(int attribute) { 101 return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL; 102 } 103 get_string(int attribute)104 void *get_string(int attribute) { 105 return mAttributes[attribute] ? nla_get_string(mAttributes[attribute]) : NULL; 106 } 107 private: 108 WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies 109 }; 110 111 class nl_iterator { 112 struct nlattr *pos; 113 int rem; 114 public: nl_iterator(struct nlattr * attr)115 nl_iterator(struct nlattr *attr) { 116 pos = (struct nlattr *)nla_data(attr); 117 rem = nla_len(attr); 118 } has_next()119 bool has_next() { 120 return nla_ok(pos, rem); 121 } next()122 void next() { 123 pos = (struct nlattr *)nla_next(pos, &(rem)); 124 } get()125 struct nlattr *get() { 126 return pos; 127 } get_type()128 uint16_t get_type() { 129 return nla_type(pos); 130 } get_u8()131 uint8_t get_u8() { 132 return nla_get_u8(pos); 133 } get_u16()134 uint16_t get_u16() { 135 return nla_get_u16(pos); 136 } get_u32()137 uint32_t get_u32() { 138 return nla_get_u32(pos); 139 } get_u64()140 uint64_t get_u64() { 141 return nla_get_u64(pos); 142 } get_data()143 void* get_data() { 144 return nla_data(pos); 145 } get_len()146 int get_len() { 147 return nla_len(pos); 148 } get_string()149 void* get_string() { 150 return nla_get_string(pos); 151 } 152 private: 153 nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies 154 }; 155 156 class WifiRequest 157 { 158 private: 159 int mFamily; 160 int mIface; 161 struct nl_msg *mMsg; 162 163 public: WifiRequest(int family)164 WifiRequest(int family) { 165 mMsg = NULL; 166 mFamily = family; 167 mIface = -1; 168 } 169 WifiRequest(int family,int iface)170 WifiRequest(int family, int iface) { 171 mMsg = NULL; 172 mFamily = family; 173 mIface = iface; 174 } 175 ~WifiRequest()176 ~WifiRequest() { 177 destroy(); 178 } 179 destroy()180 void destroy() { 181 if (mMsg) { 182 nlmsg_free(mMsg); 183 mMsg = NULL; 184 } 185 } 186 getMessage()187 nl_msg *getMessage() { 188 return mMsg; 189 } 190 191 /* Command assembly helpers */ 192 int create(int family, uint8_t cmd, int flags, int data_len); create(uint8_t cmd)193 int create(uint8_t cmd) { 194 return create(mFamily, cmd, 0, 0); 195 } 196 create_custom_len(uint8_t cmd,int data_len)197 int create_custom_len(uint8_t cmd, int data_len) { 198 return create(mFamily, cmd, 0, data_len); 199 } 200 int create(uint32_t id, int subcmd); 201 int create_custom_len(uint32_t id, int subcmd, int data_len); 202 put(int attribute,void * ptr,unsigned len)203 int put(int attribute, void *ptr, unsigned len) { 204 return nla_put(mMsg, attribute, len, ptr); 205 } put_s8(int attribute,int8_t value)206 int put_s8(int attribute, int8_t value) { 207 return nla_put(mMsg, attribute, sizeof(value), &value); 208 } put_u8(int attribute,uint8_t value)209 int put_u8(int attribute, uint8_t value) { 210 return nla_put(mMsg, attribute, sizeof(value), &value); 211 } put_u16(int attribute,uint16_t value)212 int put_u16(int attribute, uint16_t value) { 213 return nla_put(mMsg, attribute, sizeof(value), &value); 214 } put_u32(int attribute,uint32_t value)215 int put_u32(int attribute, uint32_t value) { 216 return nla_put(mMsg, attribute, sizeof(value), &value); 217 } put_u64(int attribute,uint64_t value)218 int put_u64(int attribute, uint64_t value) { 219 return nla_put(mMsg, attribute, sizeof(value), &value); 220 } put_string(int attribute,const char * value)221 int put_string(int attribute, const char *value) { 222 return nla_put(mMsg, attribute, strlen(value) + 1, value); 223 } put_addr(int attribute,mac_addr value)224 int put_addr(int attribute, mac_addr value) { 225 return nla_put(mMsg, attribute, sizeof(mac_addr), value); 226 } 227 attr_start(int attribute)228 struct nlattr * attr_start(int attribute) { 229 return nla_nest_start(mMsg, attribute); 230 } attr_end(struct nlattr * attr)231 void attr_end(struct nlattr *attr) { 232 nla_nest_end(mMsg, attr); 233 } 234 set_iface_id(int ifindex)235 int set_iface_id(int ifindex) { 236 return put_u32(NL80211_ATTR_IFINDEX, ifindex); 237 } 238 private: 239 WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies 240 241 }; 242 243 class WifiCommand 244 { 245 protected: 246 const char *mType; 247 hal_info *mInfo; 248 WifiRequest mMsg; 249 Condition mCondition; 250 wifi_request_id mId; 251 interface_info *mIfaceInfo; 252 int mRefs; 253 public: WifiCommand(const char * type,wifi_handle handle,wifi_request_id id)254 WifiCommand(const char *type, wifi_handle handle, wifi_request_id id) 255 : mType(type), mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1) 256 { 257 mIfaceInfo = NULL; 258 mInfo = getHalInfo(handle); 259 // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); 260 } 261 WifiCommand(const char * type,wifi_interface_handle iface,wifi_request_id id)262 WifiCommand(const char *type, wifi_interface_handle iface, wifi_request_id id) 263 : mType(type), mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), 264 mId(id), mRefs(1) 265 { 266 mIfaceInfo = getIfaceInfo(iface); 267 mInfo = getHalInfo(iface); 268 // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); 269 } 270 ~WifiCommand()271 virtual ~WifiCommand() { 272 // ALOGD("WifiCommand %p destroyed", this); 273 } 274 id()275 wifi_request_id id() { 276 return mId; 277 } 278 getType()279 const char *getType() { 280 return mType; 281 } 282 addRef()283 virtual void addRef() { 284 int refs = __sync_add_and_fetch(&mRefs, 1); 285 ALOGV("addRef: WifiCommand %p has %d references", this, refs); 286 } 287 releaseRef()288 virtual void releaseRef() { 289 int refs = __sync_sub_and_fetch(&mRefs, 1); 290 if (refs == 0) { 291 delete this; 292 } else { 293 // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs); 294 } 295 } 296 create()297 virtual int create() { 298 /* by default there is no way to cancel */ 299 ALOGD("WifiCommand %p can't be created", this); 300 return WIFI_ERROR_NOT_SUPPORTED; 301 } 302 cancel()303 virtual int cancel() { 304 /* by default there is no way to cancel */ 305 return WIFI_ERROR_NOT_SUPPORTED; 306 } 307 308 int requestResponse(); 309 int requestEvent(int cmd); 310 int requestVendorEvent(uint32_t id, int subcmd); 311 int requestResponse(WifiRequest& request); 312 313 protected: wifiHandle()314 wifi_handle wifiHandle() { 315 return getWifiHandle(mInfo); 316 } 317 ifaceHandle()318 wifi_interface_handle ifaceHandle() { 319 return getIfaceHandle(mIfaceInfo); 320 } 321 familyId()322 int familyId() { 323 return mInfo->nl80211_family_id; 324 } 325 ifaceId()326 int ifaceId() { 327 return mIfaceInfo->id; 328 } 329 330 /* Override this method to parse reply and dig out data; save it in the object */ handleResponse(WifiEvent & reply)331 virtual int handleResponse(WifiEvent& reply) { 332 ALOGI("skipping a response"); 333 return NL_SKIP; 334 } 335 336 /* Override this method to parse event and dig out data; save it in the object */ handleEvent(WifiEvent & event)337 virtual int handleEvent(WifiEvent& event) { 338 ALOGI("skipping an event"); 339 return NL_SKIP; 340 } 341 registerHandler(int cmd)342 int registerHandler(int cmd) { 343 return wifi_register_handler(wifiHandle(), cmd, &event_handler, this); 344 } 345 unregisterHandler(int cmd)346 void unregisterHandler(int cmd) { 347 wifi_unregister_handler(wifiHandle(), cmd); 348 } 349 registerVendorHandler(uint32_t id,int subcmd)350 int registerVendorHandler(uint32_t id, int subcmd) { 351 return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this); 352 } 353 unregisterVendorHandlerWithoutLock(uint32_t id,int subcmd)354 void unregisterVendorHandlerWithoutLock(uint32_t id, int subcmd) { 355 wifi_unregister_vendor_handler_without_lock(wifiHandle(), id, subcmd); 356 } 357 unregisterVendorHandler(uint32_t id,int subcmd)358 void unregisterVendorHandler(uint32_t id, int subcmd) { 359 wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); 360 } 361 362 private: 363 WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies 364 365 /* Event handling */ 366 static int response_handler(struct nl_msg *msg, void *arg); 367 368 static int event_handler(struct nl_msg *msg, void *arg); 369 370 /* Other event handlers */ 371 static int valid_handler(struct nl_msg *msg, void *arg); 372 373 static int ack_handler(struct nl_msg *msg, void *arg); 374 375 static int finish_handler(struct nl_msg *msg, void *arg); 376 377 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg); 378 }; 379 380 /* nl message processing macros (required to pass C++ type checks) */ 381 382 #define for_each_attr(pos, nla, rem) \ 383 for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \ 384 nla_ok(pos, rem); \ 385 pos = (nlattr *)nla_next(pos, &(rem))) 386 387 extern void InitResponseLock(); 388 extern void DestroyResponseLock(); 389