mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 04:32:37 +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 {
|
||||
uint32_t index;
|
||||
uint8_t preauth_bssid[ETH_ALEN];
|
||||
struct signal_agent *signal_agent;
|
||||
|
||||
struct wiphy *wiphy;
|
||||
struct netdev *netdev;
|
||||
@ -61,12 +60,6 @@ struct device {
|
||||
uint32_t ap_roam_watch;
|
||||
};
|
||||
|
||||
struct signal_agent {
|
||||
char *owner;
|
||||
char *path;
|
||||
unsigned int disconnect_watch;
|
||||
};
|
||||
|
||||
static uint32_t netdev_watch;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
void *user_data)
|
||||
{
|
||||
@ -408,11 +370,7 @@ static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||
station_ok_rssi(station);
|
||||
break;
|
||||
case NETDEV_EVENT_RSSI_LEVEL_NOTIFY:
|
||||
if (device->signal_agent)
|
||||
device_signal_agent_notify(device->signal_agent,
|
||||
netdev_get_path(netdev),
|
||||
netdev_get_rssi_level(netdev));
|
||||
|
||||
station_rssi_level_changed(station);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct l_dbus_message *message,
|
||||
void *user_data)
|
||||
@ -977,12 +825,6 @@ static void setup_device_interface(struct l_dbus_interface *interface)
|
||||
l_dbus_interface_method(interface, "GetOrderedNetworks", 0,
|
||||
device_get_networks, "a(osns)", "",
|
||||
"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,
|
||||
device_connect_hidden_network, "", "s", "name");
|
||||
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)
|
||||
{
|
||||
struct l_dbus *dbus;
|
||||
struct l_dbus *dbus = dbus_get_bus();
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const struct l_queue_entry *entry;
|
||||
@ -1663,6 +1823,12 @@ void station_free(struct station *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)
|
||||
dbus_pending_reply(&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)
|
||||
{
|
||||
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)
|
||||
|
@ -54,6 +54,7 @@ struct station {
|
||||
struct l_dbus_message *connect_pending;
|
||||
struct l_dbus_message *disconnect_pending;
|
||||
struct l_dbus_message *scan_pending;
|
||||
struct signal_agent *signal_agent;
|
||||
|
||||
/* Roaming related members */
|
||||
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);
|
||||
|
||||
void station_rssi_level_changed(struct station *station);
|
||||
|
||||
struct station *station_find(uint32_t ifindex);
|
||||
void station_foreach(station_foreach_func_t func, void *user_data);
|
||||
struct station *station_create(struct wiphy *wiphy, struct netdev *netdev);
|
||||
|
Loading…
Reference in New Issue
Block a user