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_s
->ucode
.idx
= wpa_ucode_registry_add(iface_registry
, val
);
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(ucv_string_new(wpa_s
->ifname
)));
88 uc_value_push(ucv_get(val
));
89 uc_value_push(ucv_get(ucv_string_new(state
)));
90 ucv_put(wpa_ucode_call(3));
94 void wpas_ucode_event(struct wpa_supplicant
*wpa_s
, int event
, union wpa_event_data
*data
)
99 if (event
!= EVENT_CH_SWITCH_STARTED
)
102 val
= wpa_ucode_registry_get(iface_registry
, wpa_s
->ucode
.idx
);
106 if (wpa_ucode_call_prepare("event"))
109 uc_value_push(ucv_get(ucv_string_new(wpa_s
->ifname
)));
110 uc_value_push(ucv_get(val
));
111 uc_value_push(ucv_get(ucv_string_new(event_to_string(event
))));
112 val
= ucv_object_new(vm
);
113 uc_value_push(ucv_get(val
));
115 if (event
== EVENT_CH_SWITCH_STARTED
) {
116 ucv_object_add(val
, "csa_count", ucv_int64_new(data
->ch_switch
.count
));
117 ucv_object_add(val
, "frequency", ucv_int64_new(data
->ch_switch
.freq
));
118 ucv_object_add(val
, "sec_chan_offset", ucv_int64_new(data
->ch_switch
.ch_offset
));
119 ucv_object_add(val
, "center_freq1", ucv_int64_new(data
->ch_switch
.cf1
));
120 ucv_object_add(val
, "center_freq2", ucv_int64_new(data
->ch_switch
.cf2
));
123 ucv_put(wpa_ucode_call(4));
127 static const char *obj_stringval(uc_value_t
*obj
, const char *name
)
129 uc_value_t
*val
= ucv_object_get(obj
, name
, NULL
);
131 return ucv_string_get(val
);
135 uc_wpas_add_iface(uc_vm_t
*vm
, size_t nargs
)
137 uc_value_t
*info
= uc_fn_arg(0);
138 uc_value_t
*ifname
= ucv_object_get(info
, "iface", NULL
);
139 uc_value_t
*bridge
= ucv_object_get(info
, "bridge", NULL
);
140 uc_value_t
*config
= ucv_object_get(info
, "config", NULL
);
141 uc_value_t
*ctrl
= ucv_object_get(info
, "ctrl", NULL
);
142 struct wpa_interface iface
;
145 if (ucv_type(info
) != UC_OBJECT
)
148 iface
= (struct wpa_interface
){
150 .ifname
= ucv_string_get(ifname
),
151 .bridge_ifname
= ucv_string_get(bridge
),
152 .confname
= ucv_string_get(config
),
153 .ctrl_interface
= ucv_string_get(ctrl
),
156 if (!iface
.ifname
|| !iface
.confname
)
159 ret
= wpa_supplicant_add_iface(wpa_global
, &iface
, 0) ? 0 : -1;
160 wpas_ucode_update_interfaces();
163 return ucv_int64_new(ret
);
167 uc_wpas_remove_iface(uc_vm_t
*vm
, size_t nargs
)
169 struct wpa_supplicant
*wpa_s
= NULL
;
170 uc_value_t
*ifname_arg
= uc_fn_arg(0);
171 const char *ifname
= ucv_string_get(ifname_arg
);
177 for (wpa_s
= wpa_global
->ifaces
; wpa_s
; wpa_s
= wpa_s
->next
)
178 if (!strcmp(wpa_s
->ifname
, ifname
))
184 ret
= wpa_supplicant_remove_iface(wpa_global
, wpa_s
, 0);
185 wpas_ucode_update_interfaces();
188 return ucv_int64_new(ret
);
192 uc_wpas_iface_status(uc_vm_t
*vm
, size_t nargs
)
194 struct wpa_supplicant
*wpa_s
= uc_fn_thisval("wpas.iface");
196 uc_value_t
*ret
, *val
;
201 ret
= ucv_object_new(vm
);
203 val
= ucv_string_new(wpa_supplicant_state_txt(wpa_s
->wpa_state
));
204 ucv_object_add(ret
, "state", ucv_get(val
));
206 bss
= wpa_s
->current_bss
;
211 ie
= wpa_bss_get_ie(bss
, WLAN_EID_HT_OPERATION
);
212 if (ie
&& ie
[1] >= 2) {
213 const struct ieee80211_ht_operation
*ht_oper
;
215 ht_oper
= (const void *) (ie
+ 2);
216 if (ht_oper
->ht_param
& HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
218 else if (ht_oper
->ht_param
&
219 HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
223 ucv_object_add(ret
, "sec_chan_offset", ucv_int64_new(sec_chan
));
224 ucv_object_add(ret
, "frequency", ucv_int64_new(bss
->freq
));
230 int wpas_ucode_init(struct wpa_global
*gl
)
232 static const uc_function_list_t global_fns
[] = {
233 { "printf", uc_wpa_printf
},
234 { "getpid", uc_wpa_getpid
},
235 { "add_iface", uc_wpas_add_iface
},
236 { "remove_iface", uc_wpas_remove_iface
},
238 static const uc_function_list_t iface_fns
[] = {
239 { "status", uc_wpas_iface_status
},
241 uc_value_t
*data
, *proto
;
244 vm
= wpa_ucode_create_vm();
246 global_type
= uc_type_declare(vm
, "wpas.global", global_fns
, NULL
);
247 iface_type
= uc_type_declare(vm
, "wpas.iface", iface_fns
, NULL
);
249 iface_registry
= ucv_array_new(vm
);
250 uc_vm_registry_set(vm
, "wpas.iface_registry", iface_registry
);
252 global
= wpa_ucode_global_init("wpas", global_type
);
254 if (wpa_ucode_run(HOSTAPD_UC_PATH
"wpa_supplicant.uc"))
265 void wpas_ucode_free(void)
267 if (wpa_ucode_call_prepare("shutdown") == 0)
268 ucv_put(wpa_ucode_call(0));