1
2#include <stdlib.h>
3#include <linux/pkt_sched.h>
4#include <netlink/object-api.h>
5#include <netlink/handlers.h>
6
7#include "wifi_hal.h"
8#include "common.h"
9
10interface_info *getIfaceInfo(wifi_interface_handle handle)
11{
12    return (interface_info *)handle;
13}
14
15wifi_handle getWifiHandle(wifi_interface_handle handle)
16{
17    return getIfaceInfo(handle)->handle;
18}
19
20hal_info *getHalInfo(wifi_handle handle)
21{
22    return (hal_info *)handle;
23}
24
25hal_info *getHalInfo(wifi_interface_handle handle)
26{
27    return getHalInfo(getWifiHandle(handle));
28}
29
30wifi_handle getWifiHandle(hal_info *info)
31{
32    return (wifi_handle)info;
33}
34
35wifi_interface_handle getIfaceHandle(interface_info *info)
36{
37    return (wifi_interface_handle)info;
38}
39
40wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg)
41{
42    hal_info *info = (hal_info *)handle;
43
44    /* TODO: check for multiple handlers? */
45    pthread_mutex_lock(&info->cb_lock);
46
47    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
48
49    if (info->num_event_cb < info->alloc_event_cb) {
50        info->event_cb[info->num_event_cb].nl_cmd  = cmd;
51        info->event_cb[info->num_event_cb].vendor_id  = 0;
52        info->event_cb[info->num_event_cb].vendor_subcmd  = 0;
53        info->event_cb[info->num_event_cb].cb_func = func;
54        info->event_cb[info->num_event_cb].cb_arg  = arg;
55        ALOGI("Successfully added event handler %p:%p for command %d at %d",
56                arg, func, cmd, info->num_event_cb);
57        info->num_event_cb++;
58        result = WIFI_SUCCESS;
59    }
60
61    pthread_mutex_unlock(&info->cb_lock);
62    return result;
63}
64
65wifi_error wifi_register_vendor_handler(wifi_handle handle,
66        uint32_t id, int subcmd, nl_recvmsg_msg_cb_t func, void *arg)
67{
68    hal_info *info = (hal_info *)handle;
69
70    /* TODO: check for multiple handlers? */
71    pthread_mutex_lock(&info->cb_lock);
72
73    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
74
75    if (info->num_event_cb < info->alloc_event_cb) {
76        info->event_cb[info->num_event_cb].nl_cmd  = NL80211_CMD_VENDOR;
77        info->event_cb[info->num_event_cb].vendor_id  = id;
78        info->event_cb[info->num_event_cb].vendor_subcmd  = subcmd;
79        info->event_cb[info->num_event_cb].cb_func = func;
80        info->event_cb[info->num_event_cb].cb_arg  = arg;
81        ALOGI("Added event handler %p:%p for vendor 0x%0x and subcmd 0x%0x at %d",
82                arg, func, id, subcmd, info->num_event_cb);
83        info->num_event_cb++;
84        result = WIFI_SUCCESS;
85    }
86
87    pthread_mutex_unlock(&info->cb_lock);
88    return result;
89}
90
91void wifi_unregister_handler(wifi_handle handle, int cmd)
92{
93    hal_info *info = (hal_info *)handle;
94
95    if (cmd == NL80211_CMD_VENDOR) {
96        ALOGE("Must use wifi_unregister_vendor_handler to remove vendor handlers");
97        return;
98    }
99
100    pthread_mutex_lock(&info->cb_lock);
101
102    for (int i = 0; i < info->num_event_cb; i++) {
103        if (info->event_cb[i].nl_cmd == cmd) {
104            ALOGI("Successfully removed event handler %p:%p for cmd = 0x%0x from %d",
105                    info->event_cb[i].cb_arg, info->event_cb[i].cb_func, cmd, i);
106
107            memmove(&info->event_cb[i], &info->event_cb[i+1],
108                (info->num_event_cb - i - 1) * sizeof(cb_info));
109            info->num_event_cb--;
110            break;
111        }
112    }
113
114    pthread_mutex_unlock(&info->cb_lock);
115}
116
117void wifi_unregister_vendor_handler(wifi_handle handle, uint32_t id, int subcmd)
118{
119    hal_info *info = (hal_info *)handle;
120
121    pthread_mutex_lock(&info->cb_lock);
122
123    for (int i = 0; i < info->num_event_cb; i++) {
124
125        if (info->event_cb[i].nl_cmd == NL80211_CMD_VENDOR
126                && info->event_cb[i].vendor_id == id
127                && info->event_cb[i].vendor_subcmd == subcmd) {
128            ALOGI("Successfully removed event handler %p:%p for vendor 0x%0x, subcmd 0x%0x from %d",
129                    info->event_cb[i].cb_arg, info->event_cb[i].cb_func, id, subcmd, i);
130            memmove(&info->event_cb[i], &info->event_cb[i+1],
131                (info->num_event_cb - i - 1) * sizeof(cb_info));
132            info->num_event_cb--;
133            break;
134        }
135    }
136
137    pthread_mutex_unlock(&info->cb_lock);
138}
139
140
141wifi_error wifi_register_cmd(wifi_handle handle, int id, WifiCommand *cmd)
142{
143    hal_info *info = (hal_info *)handle;
144
145    ALOGD("registering command %d", id);
146
147    wifi_error result = WIFI_ERROR_OUT_OF_MEMORY;
148
149    if (info->num_cmd < info->alloc_cmd) {
150        info->cmd[info->num_cmd].id   = id;
151        info->cmd[info->num_cmd].cmd  = cmd;
152        ALOGI("Successfully added command %d: %p at %d", id, cmd, info->num_cmd);
153        info->num_cmd++;
154        result = WIFI_SUCCESS;
155    }
156
157    return result;
158}
159
160WifiCommand *wifi_unregister_cmd(wifi_handle handle, int id)
161{
162    hal_info *info = (hal_info *)handle;
163
164    ALOGD("un-registering command %d", id);
165
166    WifiCommand *cmd = NULL;
167
168    for (int i = 0; i < info->num_cmd; i++) {
169        if (info->cmd[i].id == id) {
170            cmd = info->cmd[i].cmd;
171            memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
172            info->num_cmd--;
173            ALOGI("Successfully removed command %d: %p from %d", id, cmd, i);
174            break;
175        }
176    }
177
178    return cmd;
179}
180
181WifiCommand *wifi_get_cmd(wifi_handle handle, int id)
182{
183    hal_info *info = (hal_info *)handle;
184
185    WifiCommand *cmd = NULL;
186
187    for (int i = 0; i < info->num_cmd; i++) {
188        if (info->cmd[i].id == id) {
189            cmd = info->cmd[i].cmd;
190            break;
191        }
192    }
193
194    return cmd;
195}
196
197void wifi_unregister_cmd(wifi_handle handle, WifiCommand *cmd)
198{
199    hal_info *info = (hal_info *)handle;
200
201    for (int i = 0; i < info->num_cmd; i++) {
202        if (info->cmd[i].cmd == cmd) {
203            int id = info->cmd[i].id;
204            memmove(&info->cmd[i], &info->cmd[i+1], (info->num_cmd - i) * sizeof(cmd_info));
205            info->num_cmd--;
206            ALOGI("Successfully removed command %d: %p from %d", id, cmd, i);
207            break;
208        }
209    }
210}
211