1 #include "utils/includes.h"
2 #include "utils/common.h"
3 #include "utils/ucode.h"
4 #include "drivers/driver.h"
5 #include "wpa_supplicant_i.h"
6 #include "wps_supplicant.h"
10 static struct wpa_global
*wpa_global
;
11 static uc_resource_type_t
*global_type
, *iface_type
;
12 static uc_value_t
*global
, *iface_registry
;
16 wpas_ucode_iface_get_uval(struct wpa_supplicant
*wpa_s
)
21 return wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
23 val
= uc_resource_new(iface_type
, wpa_s
);
24 wpa_ucode_registry_add(iface_registry
, val
, &wpa_s
->ucode
.idx
);
30 wpas_ucode_update_interfaces(void)
32 uc_value_t
*ifs
= ucv_object_new(vm
);
33 struct wpa_supplicant
*wpa_s
;
36 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
37 ucv_object_add(ifs
, wpa_s
->ifname
, ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
39 ucv_object_add(ucv_prototype_get(global
), "interfaces", ucv_get(ifs
));
43 void wpas_ucode_add_bss(struct wpa_supplicant
*wpa_s
)
47 if (wpa_ucode_call_prepare("iface_add"))
50 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
51 uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s
)));
52 ucv_put(wpa_ucode_call(2));
56 void wpas_ucode_free_bss(struct wpa_supplicant
*wpa_s
)
60 val
= wpa_ucode_registry_remove(iface_registry
, wpa_s
->ucode
.idx
);
65 if (wpa_ucode_call_prepare("iface_remove"))
68 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
69 uc_value_push(ucv_get(val
));
70 ucv_put(wpa_ucode_call(2));
74 void wpas_ucode_update_state(struct wpa_supplicant
*wpa_s
)
79 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
83 if (wpa_ucode_call_prepare("state"))
86 state
= wpa_supplicant_state_txt(wpa_s
->wpa_state
);
87 uc_value_push(ucv_get(val
));
88 uc_value_push(ucv_get(ucv_string_new(state
)));
89 ucv_put(wpa_ucode_call(2));
93 void wpas_ucode_event(struct wpa_supplicant
*wpa_s
, int event
, union wpa_event_data
*data
)
98 if (event
!= EVENT_CH_SWITCH_STARTED
)
101 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
105 if (wpa_ucode_call_prepare("event"))
108 uc_value_push(ucv_get(val
));
109 uc_value_push(ucv_get(ucv_string_new(event_to_string(event
))));
110 val
= ucv_object_new(vm
);
111 uc_value_push(ucv_get(val
));
113 if (event
== EVENT_CH_SWITCH_STARTED
) {
114 ucv_object_add(val
, "csa_count", ucv_int64_new(data
->ch_switch
.count
));
115 ucv_object_add(val
, "frequency", ucv_int64_new(data
->ch_switch
.freq
));
116 ucv_object_add(val
, "sec_chan_offset", ucv_int64_new(data
->ch_switch
.ch_offset
));
117 ucv_object_add(val
, "center_freq1", ucv_int64_new(data
->ch_switch
.cf1
));
118 ucv_object_add(val
, "center_freq2", ucv_int64_new(data
->ch_switch
.cf2
));
121 ucv_put(wpa_ucode_call(3));
125 static const char *obj_stringval(uc_value_t
*obj
, const char *name
)
127 uc_value_t
*val
= ucv_object_get(obj
, name
, NULL
);
129 return ucv_string_get(val
);
133 uc_wpas_add_iface(uc_vm_t
*vm
, size_t nargs
)
135 uc_value_t
*info
= uc_fn_arg(0);
136 uc_value_t
*ifname
= ucv_object_get(info
, "iface", NULL
);
137 uc_value_t
*bridge
= ucv_object_get(info
, "bridge", NULL
);
138 uc_value_t
*config
= ucv_object_get(info
, "config", NULL
);
139 uc_value_t
*ctrl
= ucv_object_get(info
, "ctrl", NULL
);
140 struct wpa_interface iface
;
143 if (ucv_type(info
) != UC_OBJECT
)
146 iface
= (struct wpa_interface
){
148 .ifname
= ucv_string_get(ifname
),
149 .bridge_ifname
= ucv_string_get(bridge
),
150 .confname
= ucv_string_get(config
),
151 .ctrl_interface
= ucv_string_get(ctrl
),
154 if (!iface
.ifname
|| !iface
.confname
)
157 ret
= wpa_supplicant_add_iface(wpa_global
, &iface
, 0) ? 0 : -1;
158 wpas_ucode_update_interfaces();
161 return ucv_int64_new(ret
);
165 uc_wpas_remove_iface(uc_vm_t
*vm
, size_t nargs
)
167 struct wpa_supplicant
*wpa_s
= NULL
;
168 uc_value_t
*ifname_arg
= uc_fn_arg(0);
169 const char *ifname
= ucv_string_get(ifname_arg
);
175 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
176 if (!strcmp(wpa_s
->ifname
, ifname
))
182 ret
= wpa_supplicant_remove_iface(wpa_global
, wpa_s
, 0);
183 wpas_ucode_update_interfaces();
186 return ucv_int64_new(ret
);
190 uc_wpas_iface_status(uc_vm_t
*vm
, size_t nargs
)
192 struct wpa_supplicant
*wpa_s
= uc_fn_thisval("wpas.iface");
194 uc_value_t
*ret
, *val
;
199 ret
= ucv_object_new(vm
);
201 val
= ucv_string_new(wpa_supplicant_state_txt(wpa_s
->wpa_state
));
202 ucv_object_add(ret
, "state", ucv_get(val
));
204 bss
= wpa_s
->current_bss
;
209 ie
= wpa_bss_get_ie(bss
, WLAN_EID_HT_OPERATION
);
210 if (ie
&& ie
[1] >= 2) {
211 const struct ieee80211_ht_operation
*ht_oper
;
213 ht_oper
= (const void *) (ie
+ 2);
214 if (ht_oper
->ht_param
& HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
216 else if (ht_oper
->ht_param
&
217 HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
221 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(sec_chan
));
222 ucv_object_add(ret
, "frequency", ucv_int64_new(bss
->freq
));
228 int wpas_ucode_init(struct wpa_global
*gl
)
230 static const uc_function_list_t global_fns
[] = {
231 { "printf", uc_wpa_printf
},
232 { "getpid", uc_wpa_getpid
},
233 { "add_iface", uc_wpas_add_iface
},
234 { "remove_iface", uc_wpas_remove_iface
},
236 static const uc_function_list_t iface_fns
[] = {
237 { "status", uc_wpas_iface_status
},
239 uc_value_t
*data
, *proto
;
242 vm
= wpa_ucode_create_vm();
244 global_type
= uc_type_declare(vm
, "wpas.global", global_fns
, NULL
);
245 iface_type
= uc_type_declare(vm
, "wpas.iface", iface_fns
, NULL
);
247 iface_registry
= ucv_array_new(vm
);
248 uc_vm_registry_set(vm
, "hostap.iface_registry", iface_registry
);
250 global
= wpa_ucode_global_init("wpas", global_type
);
252 if (wpa_ucode_run(HOSTAPD_UC_PATH
"wpa_supplicant.uc"))
263 void wpas_ucode_free(void)
265 if (wpa_ucode_call_prepare("shutdown") == 0)
266 ucv_put(wpa_ucode_call(0));