1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Portions copyright (C) 2023 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 
201     int create(uint32_t id, int subcmd);
202     int create_custom_len(uint32_t id, int subcmd, int data_len);
203 
put(int attribute,void * ptr,unsigned len)204     int put(int attribute, void *ptr, unsigned len) {
205         return nla_put(mMsg, attribute, len, ptr);
206     }
put_s8(int attribute,int8_t value)207     int put_s8(int attribute, int8_t value) {
208         return nla_put(mMsg, attribute, sizeof(value), &value);
209     }
put_u8(int attribute,uint8_t value)210     int put_u8(int attribute, uint8_t value) {
211         return nla_put(mMsg, attribute, sizeof(value), &value);
212     }
put_u16(int attribute,uint16_t value)213     int put_u16(int attribute, uint16_t value) {
214         return nla_put(mMsg, attribute, sizeof(value), &value);
215     }
put_u32(int attribute,uint32_t value)216     int put_u32(int attribute, uint32_t value) {
217         return nla_put(mMsg, attribute, sizeof(value), &value);
218     }
put_u64(int attribute,uint64_t value)219     int put_u64(int attribute, uint64_t value) {
220         return nla_put(mMsg, attribute, sizeof(value), &value);
221     }
put_string(int attribute,const char * value)222     int put_string(int attribute, const char *value) {
223         return nla_put(mMsg, attribute, strlen(value) + 1, value);
224     }
put_addr(int attribute,mac_addr value)225     int put_addr(int attribute, mac_addr value) {
226         return nla_put(mMsg, attribute, sizeof(mac_addr), value);
227     }
228 
attr_start(int attribute)229     struct nlattr * attr_start(int attribute) {
230         return nla_nest_start(mMsg, attribute);
231     }
attr_end(struct nlattr * attr)232     void attr_end(struct nlattr *attr) {
233         nla_nest_end(mMsg, attr);
234     }
235 
set_iface_id(int ifindex)236     int set_iface_id(int ifindex) {
237         return put_u32(NL80211_ATTR_IFINDEX, ifindex);
238     }
239 private:
240     WifiRequest(const WifiRequest&);        // hide copy constructor to prevent copies
241 
242 };
243 
244 class WifiCommand
245 {
246 protected:
247     const char *mType;
248     hal_info *mInfo;
249     WifiRequest mMsg;
250     Condition mCondition;
251     wifi_request_id mId;
252     interface_info *mIfaceInfo;
253     int mRefs;
254 public:
WifiCommand(const char * type,wifi_handle handle,wifi_request_id id)255     WifiCommand(const char *type, wifi_handle handle, wifi_request_id id)
256             : mType(type), mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1)
257     {
258         mIfaceInfo = NULL;
259         mInfo = getHalInfo(handle);
260         // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
261     }
262 
WifiCommand(const char * type,wifi_interface_handle iface,wifi_request_id id)263     WifiCommand(const char *type, wifi_interface_handle iface, wifi_request_id id)
264             : mType(type), mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id),
265             mId(id), mRefs(1)
266     {
267         mIfaceInfo = getIfaceInfo(iface);
268         mInfo = getHalInfo(iface);
269         // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo);
270     }
271 
~WifiCommand()272     virtual ~WifiCommand() {
273         // ALOGD("WifiCommand %p destroyed", this);
274     }
275 
id()276     wifi_request_id id() {
277         return mId;
278     }
279 
getType()280     const char *getType() {
281         return mType;
282     }
283 
addRef()284     virtual void addRef() {
285         int refs = __sync_add_and_fetch(&mRefs, 1);
286         ALOGV("addRef: WifiCommand %p has %d references", this, refs);
287     }
288 
releaseRef()289     virtual void releaseRef() {
290         int refs = __sync_sub_and_fetch(&mRefs, 1);
291         if (refs == 0) {
292             delete this;
293         } else {
294             // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs);
295         }
296     }
297 
create()298     virtual int create() {
299         /* by default there is no way to cancel */
300         ALOGD("WifiCommand %p can't be created", this);
301         return WIFI_ERROR_NOT_SUPPORTED;
302     }
303 
cancel()304     virtual int cancel() {
305         /* by default there is no way to cancel */
306         return WIFI_ERROR_NOT_SUPPORTED;
307     }
308 
309     int requestResponse();
310     int requestEvent(int cmd);
311     int requestVendorEvent(uint32_t id, int subcmd);
312     int requestResponse(WifiRequest& request);
313 
314 protected:
wifiHandle()315     wifi_handle wifiHandle() {
316         return getWifiHandle(mInfo);
317     }
318 
ifaceHandle()319     wifi_interface_handle ifaceHandle() {
320         return getIfaceHandle(mIfaceInfo);
321     }
322 
familyId()323     int familyId() {
324         return mInfo->nl80211_family_id;
325     }
326 
ifaceId()327     int ifaceId() {
328         return mIfaceInfo->id;
329     }
330 
331     /* Override this method to parse reply and dig out data; save it in the object */
handleResponse(WifiEvent & reply)332     virtual int handleResponse(WifiEvent& reply) {
333         ALOGI("skipping a response");
334         return NL_SKIP;
335     }
336 
337     /* Override this method to parse event and dig out data; save it in the object */
handleEvent(WifiEvent & event)338     virtual int handleEvent(WifiEvent& event) {
339         ALOGI("skipping an event");
340         return NL_SKIP;
341     }
342 
registerHandler(int cmd)343     int registerHandler(int cmd) {
344         return wifi_register_handler(wifiHandle(), cmd, &event_handler, this);
345     }
346 
unregisterHandler(int cmd)347     void unregisterHandler(int cmd) {
348         wifi_unregister_handler(wifiHandle(), cmd);
349     }
350 
registerVendorHandler(uint32_t id,int subcmd)351     int registerVendorHandler(uint32_t id, int subcmd) {
352         return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this);
353     }
354 
unregisterVendorHandlerWithoutLock(uint32_t id,int subcmd)355     void unregisterVendorHandlerWithoutLock(uint32_t id, int subcmd) {
356         wifi_unregister_vendor_handler_without_lock(wifiHandle(), id, subcmd);
357     }
358 
unregisterVendorHandler(uint32_t id,int subcmd)359     void unregisterVendorHandler(uint32_t id, int subcmd) {
360         wifi_unregister_vendor_handler(wifiHandle(), id, subcmd);
361     }
362 
363 private:
364     WifiCommand(const WifiCommand& );           // hide copy constructor to prevent copies
365 
366     /* Event handling */
367     static int response_handler(struct nl_msg *msg, void *arg);
368 
369     static int event_handler(struct nl_msg *msg, void *arg);
370 
371     /* Other event handlers */
372     static int valid_handler(struct nl_msg *msg, void *arg);
373 
374     static int ack_handler(struct nl_msg *msg, void *arg);
375 
376     static int finish_handler(struct nl_msg *msg, void *arg);
377 
378     static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
379 };
380 
381 /* nl message processing macros (required to pass C++ type checks) */
382 
383 #define for_each_attr(pos, nla, rem) \
384     for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \
385         nla_ok(pos, rem); \
386         pos = (nlattr *)nla_next(pos, &(rem)))
387 
388 extern void InitResponseLock();
389 extern void DestroyResponseLock();
390