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