mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-09 04:48:10 +02:00
wifi: rework WifiData to use a separate struct for function pointers
Add a WifiDataClass struct, that is immutable and contains all the function pointers that were previously embedded in WifiData directly. They are not ever modified after creation, hence this allows to have a "static const" allocated instance of the VTable. Also rename wifi_data_deinit() to wifi_data_unref(). It does not only deinitialize the instance, instead it also frees it. Hence, rename it to "unref()".
This commit is contained in:
parent
3cb81ee063
commit
feb1fc2e73
6 changed files with 82 additions and 72 deletions
|
|
@ -7053,7 +7053,7 @@ nm_linux_platform_init (NMLinuxPlatform *self)
|
||||||
priv->delayed_action.list_master_connected = g_ptr_array_new ();
|
priv->delayed_action.list_master_connected = g_ptr_array_new ();
|
||||||
priv->delayed_action.list_refresh_link = g_ptr_array_new ();
|
priv->delayed_action.list_refresh_link = g_ptr_array_new ();
|
||||||
priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData));
|
priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData));
|
||||||
priv->wifi_data = g_hash_table_new_full (nm_direct_hash, NULL, NULL, (GDestroyNotify) wifi_utils_deinit);
|
priv->wifi_data = g_hash_table_new_full (nm_direct_hash, NULL, NULL, (GDestroyNotify) wifi_utils_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -259,11 +259,12 @@ out:
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WifiData parent;
|
WifiData parent;
|
||||||
struct nl_sock *nl_sock;
|
struct nl_sock *nl_sock;
|
||||||
int id;
|
|
||||||
struct nl_cb *nl_cb;
|
struct nl_cb *nl_cb;
|
||||||
guint32 *freqs;
|
guint32 *freqs;
|
||||||
|
int id;
|
||||||
int num_freqs;
|
int num_freqs;
|
||||||
int phy;
|
int phy;
|
||||||
|
bool can_wowlan:1;
|
||||||
} WifiDataNl80211;
|
} WifiDataNl80211;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -851,9 +852,11 @@ wifi_nl80211_get_wowlan (WifiData *data)
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl80211_wowlan_info info;
|
struct nl80211_wowlan_info info;
|
||||||
|
|
||||||
|
if (!nl80211->can_wowlan)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_WOWLAN, 0);
|
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_WOWLAN, 0);
|
||||||
nl80211_send_and_recv (nl80211, msg, nl80211_wowlan_handler, &info);
|
nl80211_send_and_recv (nl80211, msg, nl80211_wowlan_handler, &info);
|
||||||
|
|
||||||
return info.enabled;
|
return info.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1063,6 +1066,22 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
|
||||||
WifiData *
|
WifiData *
|
||||||
wifi_nl80211_init (int ifindex)
|
wifi_nl80211_init (int ifindex)
|
||||||
{
|
{
|
||||||
|
static const WifiDataClass klass = {
|
||||||
|
.struct_size = sizeof (WifiDataNl80211),
|
||||||
|
.get_mode = wifi_nl80211_get_mode,
|
||||||
|
.set_mode = wifi_nl80211_set_mode,
|
||||||
|
.set_powersave = wifi_nl80211_set_powersave,
|
||||||
|
.get_freq = wifi_nl80211_get_freq,
|
||||||
|
.find_freq = wifi_nl80211_find_freq,
|
||||||
|
.get_bssid = wifi_nl80211_get_bssid,
|
||||||
|
.get_rate = wifi_nl80211_get_rate,
|
||||||
|
.get_qual = wifi_nl80211_get_qual,
|
||||||
|
.get_wowlan = wifi_nl80211_get_wowlan,
|
||||||
|
#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS
|
||||||
|
.indicate_addressing_running = wifi_nl80211_indicate_addressing_running,
|
||||||
|
#endif
|
||||||
|
.deinit = wifi_nl80211_deinit,
|
||||||
|
};
|
||||||
WifiDataNl80211 *nl80211;
|
WifiDataNl80211 *nl80211;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl80211_device_info device_info = {};
|
struct nl80211_device_info device_info = {};
|
||||||
|
|
@ -1074,19 +1093,7 @@ wifi_nl80211_init (int ifindex)
|
||||||
nm_sprintf_buf (ifname, "if %d", ifindex);
|
nm_sprintf_buf (ifname, "if %d", ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
nl80211 = wifi_data_new (ifindex, sizeof (*nl80211));
|
nl80211 = wifi_data_new (&klass, ifindex);
|
||||||
nl80211->parent.get_mode = wifi_nl80211_get_mode;
|
|
||||||
nl80211->parent.set_mode = wifi_nl80211_set_mode;
|
|
||||||
nl80211->parent.set_powersave = wifi_nl80211_set_powersave;
|
|
||||||
nl80211->parent.get_freq = wifi_nl80211_get_freq;
|
|
||||||
nl80211->parent.find_freq = wifi_nl80211_find_freq;
|
|
||||||
nl80211->parent.get_bssid = wifi_nl80211_get_bssid;
|
|
||||||
nl80211->parent.get_rate = wifi_nl80211_get_rate;
|
|
||||||
nl80211->parent.get_qual = wifi_nl80211_get_qual;
|
|
||||||
#if HAVE_NL80211_CRITICAL_PROTOCOL_CMDS
|
|
||||||
nl80211->parent.indicate_addressing_running = wifi_nl80211_indicate_addressing_running;
|
|
||||||
#endif
|
|
||||||
nl80211->parent.deinit = wifi_nl80211_deinit;
|
|
||||||
|
|
||||||
nl80211->nl_sock = nl_socket_alloc ();
|
nl80211->nl_sock = nl_socket_alloc ();
|
||||||
if (nl80211->nl_sock == NULL)
|
if (nl80211->nl_sock == NULL)
|
||||||
|
|
@ -1154,18 +1161,15 @@ wifi_nl80211_init (int ifindex)
|
||||||
nl80211->freqs = device_info.freqs;
|
nl80211->freqs = device_info.freqs;
|
||||||
nl80211->num_freqs = device_info.num_freqs;
|
nl80211->num_freqs = device_info.num_freqs;
|
||||||
nl80211->parent.caps = device_info.caps;
|
nl80211->parent.caps = device_info.caps;
|
||||||
|
nl80211->can_wowlan = device_info.can_wowlan;
|
||||||
if (device_info.can_wowlan)
|
|
||||||
nl80211->parent.get_wowlan = wifi_nl80211_get_wowlan;
|
|
||||||
|
|
||||||
_LOGI (LOGD_PLATFORM | LOGD_WIFI,
|
_LOGI (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): using nl80211 for WiFi device control",
|
"(%s): using nl80211 for WiFi device control",
|
||||||
ifname);
|
ifname);
|
||||||
|
|
||||||
return (WifiData *) nl80211;
|
return (WifiData *) nl80211;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
wifi_utils_deinit ((WifiData *) nl80211);
|
wifi_utils_unref ((WifiData *) nl80211);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,8 @@
|
||||||
#include "nm-dbus-interface.h"
|
#include "nm-dbus-interface.h"
|
||||||
#include "wifi-utils.h"
|
#include "wifi-utils.h"
|
||||||
|
|
||||||
struct WifiData {
|
typedef struct {
|
||||||
int ifindex;
|
gsize struct_size;
|
||||||
NMDeviceWifiCapabilities caps;
|
|
||||||
|
|
||||||
NM80211Mode (*get_mode) (WifiData *data);
|
NM80211Mode (*get_mode) (WifiData *data);
|
||||||
|
|
||||||
|
|
@ -66,9 +65,14 @@ struct WifiData {
|
||||||
gboolean (*set_mesh_ssid) (WifiData *data, const guint8 *ssid, gsize len);
|
gboolean (*set_mesh_ssid) (WifiData *data, const guint8 *ssid, gsize len);
|
||||||
|
|
||||||
gboolean (*indicate_addressing_running) (WifiData *data, gboolean running);
|
gboolean (*indicate_addressing_running) (WifiData *data, gboolean running);
|
||||||
|
} WifiDataClass;
|
||||||
|
|
||||||
|
struct WifiData {
|
||||||
|
const WifiDataClass *klass;
|
||||||
|
int ifindex;
|
||||||
|
NMDeviceWifiCapabilities caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
gpointer wifi_data_new (int ifindex, gsize len);
|
gpointer wifi_data_new (const WifiDataClass *klass, int ifindex);
|
||||||
void wifi_data_free (WifiData *data);
|
|
||||||
|
|
||||||
#endif /* __WIFI_UTILS_PRIVATE_H__ */
|
#endif /* __WIFI_UTILS_PRIVATE_H__ */
|
||||||
|
|
|
||||||
|
|
@ -629,6 +629,21 @@ wext_get_caps (WifiDataWext *wext, const char *ifname, struct iw_range *range)
|
||||||
WifiData *
|
WifiData *
|
||||||
wifi_wext_init (int ifindex, gboolean check_scan)
|
wifi_wext_init (int ifindex, gboolean check_scan)
|
||||||
{
|
{
|
||||||
|
static const WifiDataClass klass = {
|
||||||
|
.struct_size = sizeof (WifiDataWext),
|
||||||
|
.get_mode = wifi_wext_get_mode,
|
||||||
|
.set_mode = wifi_wext_set_mode,
|
||||||
|
.set_powersave = wifi_wext_set_powersave,
|
||||||
|
.get_freq = wifi_wext_get_freq,
|
||||||
|
.find_freq = wifi_wext_find_freq,
|
||||||
|
.get_bssid = wifi_wext_get_bssid,
|
||||||
|
.get_rate = wifi_wext_get_rate,
|
||||||
|
.get_qual = wifi_wext_get_qual,
|
||||||
|
.deinit = wifi_wext_deinit,
|
||||||
|
.get_mesh_channel = wifi_wext_get_mesh_channel,
|
||||||
|
.set_mesh_channel = wifi_wext_set_mesh_channel,
|
||||||
|
.set_mesh_ssid = wifi_wext_set_mesh_ssid,
|
||||||
|
};
|
||||||
WifiDataWext *wext;
|
WifiDataWext *wext;
|
||||||
struct iw_range range;
|
struct iw_range range;
|
||||||
guint32 response_len = 0;
|
guint32 response_len = 0;
|
||||||
|
|
@ -643,19 +658,7 @@ wifi_wext_init (int ifindex, gboolean check_scan)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wext = wifi_data_new (ifindex, sizeof (*wext));
|
wext = wifi_data_new (&klass, ifindex);
|
||||||
wext->parent.get_mode = wifi_wext_get_mode;
|
|
||||||
wext->parent.set_mode = wifi_wext_set_mode;
|
|
||||||
wext->parent.set_powersave = wifi_wext_set_powersave;
|
|
||||||
wext->parent.get_freq = wifi_wext_get_freq;
|
|
||||||
wext->parent.find_freq = wifi_wext_find_freq;
|
|
||||||
wext->parent.get_bssid = wifi_wext_get_bssid;
|
|
||||||
wext->parent.get_rate = wifi_wext_get_rate;
|
|
||||||
wext->parent.get_qual = wifi_wext_get_qual;
|
|
||||||
wext->parent.deinit = wifi_wext_deinit;
|
|
||||||
wext->parent.get_mesh_channel = wifi_wext_get_mesh_channel;
|
|
||||||
wext->parent.set_mesh_channel = wifi_wext_set_mesh_channel;
|
|
||||||
wext->parent.set_mesh_ssid = wifi_wext_set_mesh_ssid;
|
|
||||||
|
|
||||||
wext->fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
wext->fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||||
if (wext->fd < 0)
|
if (wext->fd < 0)
|
||||||
|
|
@ -731,7 +734,7 @@ wifi_wext_init (int ifindex, gboolean check_scan)
|
||||||
return (WifiData *) wext;
|
return (WifiData *) wext;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
wifi_utils_deinit ((WifiData *) wext);
|
wifi_utils_unref ((WifiData *) wext);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,22 +38,19 @@
|
||||||
#include "platform/nm-platform-utils.h"
|
#include "platform/nm-platform-utils.h"
|
||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
wifi_data_new (int ifindex, gsize len)
|
wifi_data_new (const WifiDataClass *klass, int ifindex)
|
||||||
{
|
{
|
||||||
WifiData *data;
|
WifiData *data;
|
||||||
|
|
||||||
data = g_malloc0 (len);
|
nm_assert (klass);
|
||||||
|
nm_assert (klass->struct_size > sizeof (WifiData));
|
||||||
|
|
||||||
|
data = g_malloc0 (klass->struct_size);
|
||||||
|
data->klass = klass;
|
||||||
data->ifindex = ifindex;
|
data->ifindex = ifindex;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wifi_data_free (WifiData *data)
|
|
||||||
{
|
|
||||||
memset (data, 0, sizeof (*data));
|
|
||||||
g_free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
WifiData *
|
WifiData *
|
||||||
|
|
@ -85,14 +82,14 @@ wifi_utils_get_caps (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, NM_WIFI_DEVICE_CAP_NONE);
|
g_return_val_if_fail (data != NULL, NM_WIFI_DEVICE_CAP_NONE);
|
||||||
|
|
||||||
return data->caps;
|
return data->caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
NM80211Mode
|
NM80211Mode
|
||||||
wifi_utils_get_mode (WifiData *data)
|
wifi_utils_get_mode (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, NM_802_11_MODE_UNKNOWN);
|
g_return_val_if_fail (data != NULL, NM_802_11_MODE_UNKNOWN);
|
||||||
return data->get_mode (data);
|
return data->klass->get_mode (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
@ -104,7 +101,7 @@ wifi_utils_set_mode (WifiData *data, const NM80211Mode mode)
|
||||||
|| (mode == NM_802_11_MODE_ADHOC), FALSE);
|
|| (mode == NM_802_11_MODE_ADHOC), FALSE);
|
||||||
|
|
||||||
/* nl80211 probably doesn't need this */
|
/* nl80211 probably doesn't need this */
|
||||||
return data->set_mode ? data->set_mode (data, mode) : TRUE;
|
return data->klass->set_mode ? data->klass->set_mode (data, mode) : TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
@ -112,14 +109,14 @@ wifi_utils_set_powersave (WifiData *data, guint32 powersave)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
|
|
||||||
return data->set_powersave ? data->set_powersave (data, powersave) : TRUE;
|
return data->klass->set_powersave ? data->klass->set_powersave (data, powersave) : TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32
|
guint32
|
||||||
wifi_utils_get_freq (WifiData *data)
|
wifi_utils_get_freq (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, 0);
|
g_return_val_if_fail (data != NULL, 0);
|
||||||
return data->get_freq (data);
|
return data->klass->get_freq (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32
|
guint32
|
||||||
|
|
@ -127,7 +124,7 @@ wifi_utils_find_freq (WifiData *data, const guint32 *freqs)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, 0);
|
g_return_val_if_fail (data != NULL, 0);
|
||||||
g_return_val_if_fail (freqs != NULL, 0);
|
g_return_val_if_fail (freqs != NULL, 0);
|
||||||
return data->find_freq (data, freqs);
|
return data->klass->find_freq (data, freqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
@ -137,38 +134,40 @@ wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid)
|
||||||
g_return_val_if_fail (out_bssid != NULL, FALSE);
|
g_return_val_if_fail (out_bssid != NULL, FALSE);
|
||||||
|
|
||||||
memset (out_bssid, 0, ETH_ALEN);
|
memset (out_bssid, 0, ETH_ALEN);
|
||||||
return data->get_bssid (data, out_bssid);
|
return data->klass->get_bssid (data, out_bssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32
|
guint32
|
||||||
wifi_utils_get_rate (WifiData *data)
|
wifi_utils_get_rate (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, 0);
|
g_return_val_if_fail (data != NULL, 0);
|
||||||
return data->get_rate (data);
|
return data->klass->get_rate (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wifi_utils_get_qual (WifiData *data)
|
wifi_utils_get_qual (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, 0);
|
g_return_val_if_fail (data != NULL, 0);
|
||||||
return data->get_qual (data);
|
return data->klass->get_qual (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
wifi_utils_get_wowlan (WifiData *data)
|
wifi_utils_get_wowlan (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, 0);
|
g_return_val_if_fail (data != NULL, 0);
|
||||||
if (!data->get_wowlan)
|
|
||||||
|
if (!data->klass->get_wowlan)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return data->get_wowlan (data);
|
return data->klass->get_wowlan (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wifi_utils_deinit (WifiData *data)
|
wifi_utils_unref (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_if_fail (data != NULL);
|
g_return_if_fail (data != NULL);
|
||||||
data->deinit (data);
|
|
||||||
wifi_data_free (data);
|
data->klass->deinit (data);
|
||||||
|
g_free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
@ -191,8 +190,8 @@ guint32
|
||||||
wifi_utils_get_mesh_channel (WifiData *data)
|
wifi_utils_get_mesh_channel (WifiData *data)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
g_return_val_if_fail (data->get_mesh_channel != NULL, FALSE);
|
g_return_val_if_fail (data->klass->get_mesh_channel != NULL, FALSE);
|
||||||
return data->get_mesh_channel (data);
|
return data->klass->get_mesh_channel (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
@ -200,24 +199,24 @@ wifi_utils_set_mesh_channel (WifiData *data, guint32 channel)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
g_return_val_if_fail (channel <= 13, FALSE);
|
g_return_val_if_fail (channel <= 13, FALSE);
|
||||||
g_return_val_if_fail (data->set_mesh_channel != NULL, FALSE);
|
g_return_val_if_fail (data->klass->set_mesh_channel != NULL, FALSE);
|
||||||
return data->set_mesh_channel (data, channel);
|
return data->klass->set_mesh_channel (data, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
|
wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
g_return_val_if_fail (data->set_mesh_ssid != NULL, FALSE);
|
g_return_val_if_fail (data->klass->set_mesh_ssid != NULL, FALSE);
|
||||||
return data->set_mesh_ssid (data, ssid, len);
|
return data->klass->set_mesh_ssid (data, ssid, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
wifi_utils_indicate_addressing_running (WifiData *data, gboolean running)
|
wifi_utils_indicate_addressing_running (WifiData *data, gboolean running)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
if (data->indicate_addressing_running)
|
if (data->klass->indicate_addressing_running)
|
||||||
return data->indicate_addressing_running (data, running);
|
return data->klass->indicate_addressing_running (data, running);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ WifiData *wifi_utils_init (int ifindex, gboolean check_scan);
|
||||||
|
|
||||||
int wifi_utils_get_ifindex (WifiData *data);
|
int wifi_utils_get_ifindex (WifiData *data);
|
||||||
|
|
||||||
void wifi_utils_deinit (WifiData *data);
|
void wifi_utils_unref (WifiData *data);
|
||||||
|
|
||||||
NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data);
|
NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue