* of setting a regulatory domain.
*/
int (*set_country)(void *priv, const char *alpha2);
+
+ /**
+ * global_init - Global driver initialization
+ * Returns: Pointer to private data (global), %NULL on failure
+ *
+ * This optional function is called to initialize the driver wrapper
+ * for global data, i.e., data that applies to all interfaces. If this
+ * function is implemented, global_deinit() will also need to be
+ * implemented to free the private data. The driver will also likely
+ * use init2() function instead of init() to get the pointer to global
+ * data available to per-interface initializer.
+ */
+ void * (*global_init)(void);
+
+ /**
+ * global_deinit - Global driver deinitialization
+ * @priv: private driver global data from global_init()
+ *
+ * Terminate any global driver related functionality and free the
+ * global data structure.
+ */
+ void (*global_deinit)(void *priv);
+
+ /**
+ * init2 - Initialize driver interface (with global data)
+ * @ctx: context to be used when calling wpa_supplicant functions,
+ * e.g., wpa_supplicant_event()
+ * @ifname: interface name, e.g., wlan0
+ * @global_priv: private driver global data from global_init()
+ * Returns: Pointer to private data, %NULL on failure
+ *
+ * This function can be used instead of init() if the driver wrapper
+ * uses global data.
+ */
+ void * (*init2)(void *ctx, const char *ifname, void *global_priv);
};
/* Function to check whether a driver is for wired connections */
wpa_driver_ndis_get_scan_results,
NULL /* set_probe_req_ie */,
NULL /* set_mode */,
- NULL /* set_country */
+ NULL /* set_country */,
+ NULL /* global_init */,
+ NULL /* global_deinit */,
+ NULL /* init2 */
};
wpa_driver_privsep_get_scan_results2,
NULL /* set_probe_req_ie */,
wpa_driver_privsep_set_mode,
- NULL /* set_country */
+ NULL /* set_country */,
+ NULL /* global_init */,
+ NULL /* global_deinit */,
+ NULL /* init2 */
};
#include "ieee802_11_defs.h"
+struct wpa_driver_test_global {
+ int dummy;
+};
+
struct wpa_driver_test_data {
+ struct wpa_driver_test_global *global;
void *ctx;
u8 own_addr[ETH_ALEN];
int test_socket;
}
-static void * wpa_driver_test_init(void *ctx, const char *ifname)
+static void * wpa_driver_test_init2(void *ctx, const char *ifname,
+ void *global_priv)
{
struct wpa_driver_test_data *drv;
drv = os_zalloc(sizeof(*drv));
if (drv == NULL)
return NULL;
+ drv->global = global_priv;
drv->ctx = ctx;
drv->test_socket = -1;
}
+static void * wpa_driver_test_global_init(void)
+{
+ struct wpa_driver_test_global *global;
+
+ global = os_zalloc(sizeof(*global));
+ return global;
+}
+
+
+static void wpa_driver_test_global_deinit(void *priv)
+{
+ struct wpa_driver_test_global *global = priv;
+ os_free(global);
+}
+
+
const struct wpa_driver_ops wpa_driver_test_ops = {
"test",
"wpa_supplicant test driver",
wpa_driver_test_get_ssid,
wpa_driver_test_set_wpa,
wpa_driver_test_set_key,
- wpa_driver_test_init,
+ NULL /* init */,
wpa_driver_test_deinit,
wpa_driver_test_set_param,
NULL /* set_countermeasures */,
wpa_driver_test_get_scan_results2,
wpa_driver_set_probe_req_ie,
NULL /* set_mode */,
- NULL /* set_country */
+ NULL /* set_country */,
+ wpa_driver_test_global_init,
+ wpa_driver_test_global_deinit,
+ wpa_driver_test_init2
};
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
{
struct wpa_global *global;
- int ret;
+ int ret, i;
if (params == NULL)
return NULL;
}
}
+ for (i = 0; wpa_supplicant_drivers[i]; i++)
+ global->drv_count++;
+ if (global->drv_count == 0) {
+ wpa_printf(MSG_ERROR, "No drivers enabled");
+ wpa_supplicant_deinit(global);
+ return NULL;
+ }
+ global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
+ if (global->drv_priv == NULL) {
+ wpa_supplicant_deinit(global);
+ return NULL;
+ }
+ for (i = 0; wpa_supplicant_drivers[i]; i++) {
+ if (!wpa_supplicant_drivers[i]->global_init)
+ continue;
+ global->drv_priv[i] = wpa_supplicant_drivers[i]->global_init();
+ if (global->drv_priv[i] == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to initialize driver "
+ "'%s'", wpa_supplicant_drivers[i]->name);
+ wpa_supplicant_deinit(global);
+ return NULL;
+ }
+ }
+
return global;
}
*/
void wpa_supplicant_deinit(struct wpa_global *global)
{
+ int i;
+
if (global == NULL)
return;
eap_peer_unregister_methods();
+ for (i = 0; wpa_supplicant_drivers[i]; i++) {
+ if (!global->drv_priv[i])
+ continue;
+ wpa_supplicant_drivers[i]->global_deinit(global->drv_priv[i]);
+ }
+ os_free(global->drv_priv);
+
eloop_destroy();
if (global->params.pid_file) {
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
+ void **drv_priv;
+ size_t drv_count;
};
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
const char *ifname)
{
+ if (wpa_s->driver->init2)
+ return wpa_s->driver->init2(wpa_s, ifname, wpa_s->global);
if (wpa_s->driver->init) {
return wpa_s->driver->init(wpa_s, ifname);
}