mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 13:02:44 +01:00
station: move signal level agent logic from device
This commit is contained in:
parent
ac83a35b97
commit
cdfcb902e4
170
src/device.c
170
src/device.c
@ -50,7 +50,6 @@
|
|||||||
struct device {
|
struct device {
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
uint8_t preauth_bssid[ETH_ALEN];
|
uint8_t preauth_bssid[ETH_ALEN];
|
||||||
struct signal_agent *signal_agent;
|
|
||||||
|
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct netdev *netdev;
|
struct netdev *netdev;
|
||||||
@ -61,12 +60,6 @@ struct device {
|
|||||||
uint32_t ap_roam_watch;
|
uint32_t ap_roam_watch;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct signal_agent {
|
|
||||||
char *owner;
|
|
||||||
char *path;
|
|
||||||
unsigned int disconnect_watch;
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint32_t netdev_watch;
|
static uint32_t netdev_watch;
|
||||||
|
|
||||||
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||||
@ -350,37 +343,6 @@ static void device_connect_cb(struct netdev *netdev, enum netdev_result result,
|
|||||||
station_enter_state(station, STATION_STATE_CONNECTED);
|
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_signal_agent_notify(struct signal_agent *agent,
|
|
||||||
const char *device_path, int level)
|
|
||||||
{
|
|
||||||
struct l_dbus_message *msg;
|
|
||||||
uint8_t value = level;
|
|
||||||
|
|
||||||
msg = l_dbus_message_new_method_call(dbus_get_bus(),
|
|
||||||
agent->owner, agent->path,
|
|
||||||
IWD_SIGNAL_AGENT_INTERFACE,
|
|
||||||
"Changed");
|
|
||||||
l_dbus_message_set_arguments(msg, "oy", device_path, value);
|
|
||||||
l_dbus_message_set_no_reply(msg, true);
|
|
||||||
|
|
||||||
l_dbus_send(dbus_get_bus(), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_signal_agent_release(struct signal_agent *agent,
|
|
||||||
const char *device_path)
|
|
||||||
{
|
|
||||||
struct l_dbus_message *msg;
|
|
||||||
|
|
||||||
msg = l_dbus_message_new_method_call(dbus_get_bus(),
|
|
||||||
agent->owner, agent->path,
|
|
||||||
IWD_SIGNAL_AGENT_INTERFACE,
|
|
||||||
"Release");
|
|
||||||
l_dbus_message_set_arguments(msg, "o", device_path);
|
|
||||||
l_dbus_message_set_no_reply(msg, true);
|
|
||||||
|
|
||||||
l_dbus_send(dbus_get_bus(), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
@ -408,11 +370,7 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
|||||||
station_ok_rssi(station);
|
station_ok_rssi(station);
|
||||||
break;
|
break;
|
||||||
case NETDEV_EVENT_RSSI_LEVEL_NOTIFY:
|
case NETDEV_EVENT_RSSI_LEVEL_NOTIFY:
|
||||||
if (device->signal_agent)
|
station_rssi_level_changed(station);
|
||||||
device_signal_agent_notify(device->signal_agent,
|
|
||||||
netdev_get_path(netdev),
|
|
||||||
netdev_get_rssi_level(netdev));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -514,116 +472,6 @@ static struct l_dbus_message *device_get_networks(struct l_dbus *dbus,
|
|||||||
return station_dbus_get_networks(dbus, message, station);
|
return station_dbus_get_networks(dbus, message, station);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void signal_agent_free(void *data)
|
|
||||||
{
|
|
||||||
struct signal_agent *agent = data;
|
|
||||||
|
|
||||||
l_free(agent->owner);
|
|
||||||
l_free(agent->path);
|
|
||||||
l_dbus_remove_watch(dbus_get_bus(), agent->disconnect_watch);
|
|
||||||
l_free(agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void signal_agent_disconnect(struct l_dbus *dbus, void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
|
|
||||||
l_debug("signal_agent %s disconnected", device->signal_agent->owner);
|
|
||||||
|
|
||||||
l_idle_oneshot(signal_agent_free, device->signal_agent, NULL);
|
|
||||||
device->signal_agent = NULL;
|
|
||||||
|
|
||||||
netdev_set_rssi_report_levels(device->netdev, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_dbus_message *device_signal_agent_register(struct l_dbus *dbus,
|
|
||||||
struct l_dbus_message *message,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
const char *path, *sender;
|
|
||||||
struct l_dbus_message_iter level_iter;
|
|
||||||
int8_t levels[16];
|
|
||||||
int err;
|
|
||||||
int16_t val;
|
|
||||||
size_t count = 0;
|
|
||||||
|
|
||||||
if (device->signal_agent)
|
|
||||||
return dbus_error_already_exists(message);
|
|
||||||
|
|
||||||
l_debug("signal agent register called");
|
|
||||||
|
|
||||||
if (!l_dbus_message_get_arguments(message, "oan", &path, &level_iter))
|
|
||||||
return dbus_error_invalid_args(message);
|
|
||||||
|
|
||||||
while (l_dbus_message_iter_next_entry(&level_iter, &val)) {
|
|
||||||
if (count >= L_ARRAY_SIZE(levels) || val > 127 || val < -127)
|
|
||||||
return dbus_error_invalid_args(message);
|
|
||||||
|
|
||||||
levels[count++] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 1)
|
|
||||||
return dbus_error_invalid_args(message);
|
|
||||||
|
|
||||||
err = netdev_set_rssi_report_levels(device->netdev, levels, count);
|
|
||||||
if (err == -ENOTSUP)
|
|
||||||
return dbus_error_not_supported(message);
|
|
||||||
else if (err < 0)
|
|
||||||
return dbus_error_failed(message);
|
|
||||||
|
|
||||||
sender = l_dbus_message_get_sender(message);
|
|
||||||
|
|
||||||
device->signal_agent = l_new(struct signal_agent, 1);
|
|
||||||
device->signal_agent->owner = l_strdup(sender);
|
|
||||||
device->signal_agent->path = l_strdup(path);
|
|
||||||
device->signal_agent->disconnect_watch =
|
|
||||||
l_dbus_add_disconnect_watch(dbus, sender,
|
|
||||||
signal_agent_disconnect,
|
|
||||||
device, NULL);
|
|
||||||
|
|
||||||
l_debug("agent %s path %s", sender, path);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: send an initial notification in a oneshot idle callback,
|
|
||||||
* if state is connected.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return l_dbus_message_new_method_return(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_dbus_message *device_signal_agent_unregister(
|
|
||||||
struct l_dbus *dbus,
|
|
||||||
struct l_dbus_message *message,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
const char *path, *sender;
|
|
||||||
|
|
||||||
if (!device->signal_agent)
|
|
||||||
return dbus_error_failed(message);
|
|
||||||
|
|
||||||
l_debug("signal agent unregister");
|
|
||||||
|
|
||||||
if (!l_dbus_message_get_arguments(message, "o", &path))
|
|
||||||
return dbus_error_invalid_args(message);
|
|
||||||
|
|
||||||
if (strcmp(device->signal_agent->path, path))
|
|
||||||
return dbus_error_not_found(message);
|
|
||||||
|
|
||||||
sender = l_dbus_message_get_sender(message);
|
|
||||||
|
|
||||||
if (strcmp(device->signal_agent->owner, sender))
|
|
||||||
return dbus_error_not_found(message);
|
|
||||||
|
|
||||||
signal_agent_free(device->signal_agent);
|
|
||||||
device->signal_agent = NULL;
|
|
||||||
|
|
||||||
netdev_set_rssi_report_levels(device->netdev, NULL, 0);
|
|
||||||
|
|
||||||
return l_dbus_message_new_method_return(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_dbus_message *device_connect_hidden_network(struct l_dbus *dbus,
|
static struct l_dbus_message *device_connect_hidden_network(struct l_dbus *dbus,
|
||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
@ -977,12 +825,6 @@ static void setup_device_interface(struct l_dbus_interface *interface)
|
|||||||
l_dbus_interface_method(interface, "GetOrderedNetworks", 0,
|
l_dbus_interface_method(interface, "GetOrderedNetworks", 0,
|
||||||
device_get_networks, "a(osns)", "",
|
device_get_networks, "a(osns)", "",
|
||||||
"networks");
|
"networks");
|
||||||
l_dbus_interface_method(interface, "RegisterSignalLevelAgent", 0,
|
|
||||||
device_signal_agent_register,
|
|
||||||
"", "oan", "path", "levels");
|
|
||||||
l_dbus_interface_method(interface, "UnregisterSignalLevelAgent", 0,
|
|
||||||
device_signal_agent_unregister,
|
|
||||||
"", "o", "path");
|
|
||||||
l_dbus_interface_method(interface, "ConnectHiddenNetwork", 0,
|
l_dbus_interface_method(interface, "ConnectHiddenNetwork", 0,
|
||||||
device_connect_hidden_network, "", "s", "name");
|
device_connect_hidden_network, "", "s", "name");
|
||||||
l_dbus_interface_property(interface, "Name", 0, "s",
|
l_dbus_interface_property(interface, "Name", 0, "s",
|
||||||
@ -1096,18 +938,10 @@ struct device *device_create(struct wiphy *wiphy, struct netdev *netdev)
|
|||||||
|
|
||||||
void device_remove(struct device *device)
|
void device_remove(struct device *device)
|
||||||
{
|
{
|
||||||
struct l_dbus *dbus;
|
struct l_dbus *dbus = dbus_get_bus();
|
||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
if (device->signal_agent) {
|
|
||||||
device_signal_agent_release(device->signal_agent,
|
|
||||||
netdev_get_path(device->netdev));
|
|
||||||
signal_agent_free(device->signal_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dbus = dbus_get_bus();
|
|
||||||
l_dbus_unregister_object(dbus, netdev_get_path(device->netdev));
|
l_dbus_unregister_object(dbus, netdev_get_path(device->netdev));
|
||||||
|
|
||||||
scan_ifindex_remove(device->index);
|
scan_ifindex_remove(device->index);
|
||||||
|
172
src/station.c
172
src/station.c
@ -1599,6 +1599,166 @@ struct l_dbus_message *station_dbus_scan(struct l_dbus *dbus,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct signal_agent {
|
||||||
|
char *owner;
|
||||||
|
char *path;
|
||||||
|
unsigned int disconnect_watch;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void station_signal_agent_notify(struct signal_agent *agent,
|
||||||
|
const char *device_path, int level)
|
||||||
|
{
|
||||||
|
struct l_dbus_message *msg;
|
||||||
|
uint8_t value = level;
|
||||||
|
|
||||||
|
msg = l_dbus_message_new_method_call(dbus_get_bus(),
|
||||||
|
agent->owner, agent->path,
|
||||||
|
IWD_SIGNAL_AGENT_INTERFACE,
|
||||||
|
"Changed");
|
||||||
|
l_dbus_message_set_arguments(msg, "oy", device_path, value);
|
||||||
|
l_dbus_message_set_no_reply(msg, true);
|
||||||
|
|
||||||
|
l_dbus_send(dbus_get_bus(), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void station_rssi_level_changed(struct station *station)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = station->netdev;
|
||||||
|
|
||||||
|
if (!station->signal_agent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
station_signal_agent_notify(station->signal_agent,
|
||||||
|
netdev_get_path(netdev),
|
||||||
|
netdev_get_rssi_level(netdev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_signal_agent_release(struct signal_agent *agent,
|
||||||
|
const char *device_path)
|
||||||
|
{
|
||||||
|
struct l_dbus_message *msg;
|
||||||
|
|
||||||
|
msg = l_dbus_message_new_method_call(dbus_get_bus(),
|
||||||
|
agent->owner, agent->path,
|
||||||
|
IWD_SIGNAL_AGENT_INTERFACE,
|
||||||
|
"Release");
|
||||||
|
l_dbus_message_set_arguments(msg, "o", device_path);
|
||||||
|
l_dbus_message_set_no_reply(msg, true);
|
||||||
|
|
||||||
|
l_dbus_send(dbus_get_bus(), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signal_agent_free(void *data)
|
||||||
|
{
|
||||||
|
struct signal_agent *agent = data;
|
||||||
|
|
||||||
|
l_free(agent->owner);
|
||||||
|
l_free(agent->path);
|
||||||
|
l_dbus_remove_watch(dbus_get_bus(), agent->disconnect_watch);
|
||||||
|
l_free(agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signal_agent_disconnect(struct l_dbus *dbus, void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
|
||||||
|
l_debug("signal_agent %s disconnected", station->signal_agent->owner);
|
||||||
|
|
||||||
|
l_idle_oneshot(signal_agent_free, station->signal_agent, NULL);
|
||||||
|
station->signal_agent = NULL;
|
||||||
|
|
||||||
|
netdev_set_rssi_report_levels(station->netdev, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *station_dbus_signal_agent_register(
|
||||||
|
struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
const char *path, *sender;
|
||||||
|
struct l_dbus_message_iter level_iter;
|
||||||
|
int8_t levels[16];
|
||||||
|
int err;
|
||||||
|
int16_t val;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
if (station->signal_agent)
|
||||||
|
return dbus_error_already_exists(message);
|
||||||
|
|
||||||
|
l_debug("signal agent register called");
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(message, "oan", &path, &level_iter))
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
while (l_dbus_message_iter_next_entry(&level_iter, &val)) {
|
||||||
|
if (count >= L_ARRAY_SIZE(levels) || val > 127 || val < -127)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
levels[count++] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
err = netdev_set_rssi_report_levels(station->netdev, levels, count);
|
||||||
|
if (err == -ENOTSUP)
|
||||||
|
return dbus_error_not_supported(message);
|
||||||
|
else if (err < 0)
|
||||||
|
return dbus_error_failed(message);
|
||||||
|
|
||||||
|
sender = l_dbus_message_get_sender(message);
|
||||||
|
|
||||||
|
station->signal_agent = l_new(struct signal_agent, 1);
|
||||||
|
station->signal_agent->owner = l_strdup(sender);
|
||||||
|
station->signal_agent->path = l_strdup(path);
|
||||||
|
station->signal_agent->disconnect_watch =
|
||||||
|
l_dbus_add_disconnect_watch(dbus, sender,
|
||||||
|
signal_agent_disconnect,
|
||||||
|
station, NULL);
|
||||||
|
|
||||||
|
l_debug("agent %s path %s", sender, path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: send an initial notification in a oneshot idle callback,
|
||||||
|
* if state is connected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return l_dbus_message_new_method_return(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *station_dbus_signal_agent_unregister(
|
||||||
|
struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
const char *path, *sender;
|
||||||
|
|
||||||
|
if (!station->signal_agent)
|
||||||
|
return dbus_error_failed(message);
|
||||||
|
|
||||||
|
l_debug("signal agent unregister");
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(message, "o", &path))
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
if (strcmp(station->signal_agent->path, path))
|
||||||
|
return dbus_error_not_found(message);
|
||||||
|
|
||||||
|
sender = l_dbus_message_get_sender(message);
|
||||||
|
|
||||||
|
if (strcmp(station->signal_agent->owner, sender))
|
||||||
|
return dbus_error_not_found(message);
|
||||||
|
|
||||||
|
signal_agent_free(station->signal_agent);
|
||||||
|
station->signal_agent = NULL;
|
||||||
|
|
||||||
|
netdev_set_rssi_report_levels(station->netdev, NULL, 0);
|
||||||
|
|
||||||
|
return l_dbus_message_new_method_return(message);
|
||||||
|
}
|
||||||
|
|
||||||
void station_foreach(station_foreach_func_t func, void *user_data)
|
void station_foreach(station_foreach_func_t func, void *user_data)
|
||||||
{
|
{
|
||||||
const struct l_queue_entry *entry;
|
const struct l_queue_entry *entry;
|
||||||
@ -1663,6 +1823,12 @@ void station_free(struct station *station)
|
|||||||
|
|
||||||
periodic_scan_stop(station);
|
periodic_scan_stop(station);
|
||||||
|
|
||||||
|
if (station->signal_agent) {
|
||||||
|
station_signal_agent_release(station->signal_agent,
|
||||||
|
netdev_get_path(station->netdev));
|
||||||
|
signal_agent_free(station->signal_agent);
|
||||||
|
}
|
||||||
|
|
||||||
if (station->connect_pending)
|
if (station->connect_pending)
|
||||||
dbus_pending_reply(&station->connect_pending,
|
dbus_pending_reply(&station->connect_pending,
|
||||||
dbus_error_aborted(station->connect_pending));
|
dbus_error_aborted(station->connect_pending));
|
||||||
@ -1689,6 +1855,12 @@ void station_free(struct station *station)
|
|||||||
|
|
||||||
static void station_setup_interface(struct l_dbus_interface *interface)
|
static void station_setup_interface(struct l_dbus_interface *interface)
|
||||||
{
|
{
|
||||||
|
l_dbus_interface_method(interface, "RegisterSignalLevelAgent", 0,
|
||||||
|
station_dbus_signal_agent_register,
|
||||||
|
"", "oan", "path", "levels");
|
||||||
|
l_dbus_interface_method(interface, "UnregisterSignalLevelAgent", 0,
|
||||||
|
station_dbus_signal_agent_unregister,
|
||||||
|
"", "o", "path");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void station_destroy_interface(void *user_data)
|
static void station_destroy_interface(void *user_data)
|
||||||
|
@ -54,6 +54,7 @@ struct station {
|
|||||||
struct l_dbus_message *connect_pending;
|
struct l_dbus_message *connect_pending;
|
||||||
struct l_dbus_message *disconnect_pending;
|
struct l_dbus_message *disconnect_pending;
|
||||||
struct l_dbus_message *scan_pending;
|
struct l_dbus_message *scan_pending;
|
||||||
|
struct signal_agent *signal_agent;
|
||||||
|
|
||||||
/* Roaming related members */
|
/* Roaming related members */
|
||||||
struct timespec roam_min_time;
|
struct timespec roam_min_time;
|
||||||
@ -127,6 +128,8 @@ struct l_dbus_message *station_dbus_scan(struct l_dbus *dbus,
|
|||||||
|
|
||||||
int station_disconnect(struct station *station);
|
int station_disconnect(struct station *station);
|
||||||
|
|
||||||
|
void station_rssi_level_changed(struct station *station);
|
||||||
|
|
||||||
struct station *station_find(uint32_t ifindex);
|
struct station *station_find(uint32_t ifindex);
|
||||||
void station_foreach(station_foreach_func_t func, void *user_data);
|
void station_foreach(station_foreach_func_t func, void *user_data);
|
||||||
struct station *station_create(struct wiphy *wiphy, struct netdev *netdev);
|
struct station *station_create(struct wiphy *wiphy, struct netdev *netdev);
|
||||||
|
Loading…
Reference in New Issue
Block a user