1 #include "utils/includes.h"
2 #include "utils/common.h"
3 #include "utils/ucode.h"
4 #include "drivers/driver.h"
5 #include "ap/hostapd.h"
6 #include "wpa_supplicant_i.h"
7 #include "wps_supplicant.h"
11 static struct wpa_global
*wpa_global
;
12 static uc_resource_type_t
*global_type
, *iface_type
;
13 static uc_value_t
*global
, *iface_registry
;
17 wpas_ucode_iface_get_uval(struct wpa_supplicant
*wpa_s
)
22 return wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
24 val
= uc_resource_new(iface_type
, wpa_s
);
25 wpa_s
->ucode
.idx
= wpa_ucode_registry_add(iface_registry
, val
);
31 wpas_ucode_update_interfaces(void)
33 uc_value_t
*ifs
= ucv_object_new(vm
);
34 struct wpa_supplicant
*wpa_s
;
37 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
38 ucv_object_add(ifs
, wpa_s
->ifname
, ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
40 ucv_object_add(ucv_prototype_get(global
), "interfaces", ucv_get(ifs
));
44 void wpas_ucode_add_bss(struct wpa_supplicant
*wpa_s
)
48 if (wpa_ucode_call_prepare("iface_add"))
51 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
52 uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
53 ucv_put(wpa_ucode_call(2));
57 void wpas_ucode_free_bss(struct wpa_supplicant
*wpa_s
)
61 val
= wpa_ucode_registry_remove(iface_registry
, wpa_s
->ucode
.idx
);
66 if (wpa_ucode_call_prepare("iface_remove"))
69 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
70 uc_value_push(ucv_get(val
));
71 ucv_put(wpa_ucode_call(2));
75 void wpas_ucode_update_state(struct wpa_supplicant
*wpa_s
)
80 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
84 if (wpa_ucode_call_prepare("state"))
87 state
= wpa_supplicant_state_txt(wpa_s
->wpa_state
);
88 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
89 uc_value_push(ucv_get(val
));
90 uc_value_push(ucv_get(ucv_string_new(state
)));
91 ucv_put(wpa_ucode_call(3));
95 void wpas_ucode_event(struct wpa_supplicant
*wpa_s
, int event
, union wpa_event_data
*data
)
100 if (event
!= EVENT_CH_SWITCH_STARTED
)
103 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
107 if (wpa_ucode_call_prepare("event"))
110 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
111 uc_value_push(ucv_get(val
));
112 uc_value_push(ucv_get(ucv_string_new(event_to_string(event
))));
113 val
= ucv_object_new(vm
);
114 uc_value_push(ucv_get(val
));
116 if (event
== EVENT_CH_SWITCH_STARTED
) {
117 ucv_object_add(val
, "csa_count", ucv_int64_new(data
->ch_switch
.count
));
118 ucv_object_add(val
, "frequency", ucv_int64_new(data
->ch_switch
.freq
));
119 ucv_object_add(val
, "sec_chan_offset", ucv_int64_new(data
->ch_switch
.ch_offset
));
120 ucv_object_add(val
, "center_freq1", ucv_int64_new(data
->ch_switch
.cf1
));
121 ucv_object_add(val
, "center_freq2", ucv_int64_new(data
->ch_switch
.cf2
));
124 ucv_put(wpa_ucode_call(4));
128 static const char *obj_stringval(uc_value_t
*obj
, const char *name
)
130 uc_value_t
*val
= ucv_object_get(obj
, name
, NULL
);
132 return ucv_string_get(val
);
136 uc_wpas_add_iface(uc_vm_t
*vm
, size_t nargs
)
138 uc_value_t
*info
= uc_fn_arg(0);
139 uc_value_t
*ifname
= ucv_object_get(info
, "iface", NULL
);
140 uc_value_t
*bridge
= ucv_object_get(info
, "bridge", NULL
);
141 uc_value_t
*config
= ucv_object_get(info
, "config", NULL
);
142 uc_value_t
*ctrl
= ucv_object_get(info
, "ctrl", NULL
);
143 struct wpa_interface iface
;
146 if (ucv_type(info
) != UC_OBJECT
)
149 iface
= (struct wpa_interface
){
151 .ifname
= ucv_string_get(ifname
),
152 .bridge_ifname
= ucv_string_get(bridge
),
153 .confname
= ucv_string_get(config
),
154 .ctrl_interface
= ucv_string_get(ctrl
),
157 if (!iface
.ifname
|| !iface
.confname
)
160 ret
= wpa_supplicant_add_iface(wpa_global
, &iface
, 0) ? 0 : -1;
161 wpas_ucode_update_interfaces();
164 return ucv_int64_new(ret
);
168 uc_wpas_remove_iface(uc_vm_t
*vm
, size_t nargs
)
170 struct wpa_supplicant
*wpa_s
= NULL
;
171 uc_value_t
*ifname_arg
= uc_fn_arg(0);
172 const char *ifname
= ucv_string_get(ifname_arg
);
178 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
179 if (!strcmp(wpa_s
->ifname
, ifname
))
185 ret
= wpa_supplicant_remove_iface(wpa_global
, wpa_s
, 0);
186 wpas_ucode_update_interfaces();
189 return ucv_int64_new(ret
);
193 uc_wpas_iface_status(uc_vm_t
*vm
, size_t nargs
)
195 struct wpa_supplicant
*wpa_s
= uc_fn_thisval("wpas.iface");
197 uc_value_t
*ret
, *val
;
202 ret
= ucv_object_new(vm
);
204 val
= ucv_string_new(wpa_supplicant_state_txt(wpa_s
->wpa_state
));
205 ucv_object_add(ret
, "state", ucv_get(val
));
207 bss
= wpa_s
->current_bss
;
212 ie
= wpa_bss_get_ie(bss
, WLAN_EID_HT_OPERATION
);
213 if (ie
&& ie
[1] >= 2) {
214 const struct ieee80211_ht_operation
*ht_oper
;
217 ht_oper
= (const void *) (ie
+ 2);
218 sec
= ht_oper
->ht_param
& HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK
;
219 if (sec
== HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
221 else if (sec
== HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
225 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(sec_chan
));
226 ucv_object_add(ret
, "frequency", ucv_int64_new(bss
->freq
));
231 struct hostapd_iface
*ifmsh
= wpa_s
->ifmsh
;
233 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(ifmsh
->conf
->secondary_channel
));
234 ucv_object_add(ret
, "frequency", ucv_int64_new(ifmsh
->freq
));
241 int wpas_ucode_init(struct wpa_global
*gl
)
243 static const uc_function_list_t global_fns
[] = {
244 { "printf", uc_wpa_printf
},
245 { "getpid", uc_wpa_getpid
},
246 { "add_iface", uc_wpas_add_iface
},
247 { "remove_iface", uc_wpas_remove_iface
},
249 static const uc_function_list_t iface_fns
[] = {
250 { "status", uc_wpas_iface_status
},
252 uc_value_t
*data
, *proto
;
255 vm
= wpa_ucode_create_vm();
257 global_type
= uc_type_declare(vm
, "wpas.global", global_fns
, NULL
);
258 iface_type
= uc_type_declare(vm
, "wpas.iface", iface_fns
, NULL
);
260 iface_registry
= ucv_array_new(vm
);
261 uc_vm_registry_set(vm
, "wpas.iface_registry", iface_registry
);
263 global
= wpa_ucode_global_init("wpas", global_type
);
265 if (wpa_ucode_run(HOSTAPD_UC_PATH
"wpa_supplicant.uc"))
276 void wpas_ucode_free(void)
278 if (wpa_ucode_call_prepare("shutdown") == 0)
279 ucv_put(wpa_ucode_call(0));