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 
getIfaceInfo(wifi_interface_handle handle)10 interface_info *getIfaceInfo(wifi_interface_handle handle)
11 {
12     return (interface_info *)handle;
13 }
14 
getWifiHandle(wifi_interface_handle handle)15 wifi_handle getWifiHandle(wifi_interface_handle handle)
16 {
17     return getIfaceInfo(handle)->handle;
18 }
19 
getHalInfo(wifi_handle handle)20 hal_info *getHalInfo(wifi_handle handle)
21 {
22     return (hal_info *)handle;
23 }
24 
getHalInfo(wifi_interface_handle handle)25 hal_info *getHalInfo(wifi_interface_handle handle)
26 {
27     return getHalInfo(getWifiHandle(handle));
28 }
29 
getWifiHandle(hal_info * info)30 wifi_handle getWifiHandle(hal_info *info)
31 {
32     return (wifi_handle)info;
33 }
34 
getIfaceHandle(interface_info * info)35 wifi_interface_handle getIfaceHandle(interface_info *info)
36 {
37     return (wifi_interface_handle)info;
38 }
39 
wifi_register_handler(wifi_handle handle,int cmd,nl_recvmsg_msg_cb_t func,void * arg)40 wifi_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 
wifi_register_vendor_handler(wifi_handle handle,uint32_t id,int subcmd,nl_recvmsg_msg_cb_t func,void * arg)65 wifi_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 
wifi_unregister_handler(wifi_handle handle,int cmd)91 void 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 
wifi_unregister_vendor_handler(wifi_handle handle,uint32_t id,int subcmd)117 void 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 
wifi_register_cmd(wifi_handle handle,int id,WifiCommand * cmd)141 wifi_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 
wifi_unregister_cmd(wifi_handle handle,int id)160 WifiCommand *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 
wifi_get_cmd(wifi_handle handle,int id)181 WifiCommand *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 
wifi_unregister_cmd(wifi_handle handle,WifiCommand * cmd)197 void 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