mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-28 21:19:24 +01:00
hwsim: DBus methods for creating and destroying radios
This commit is contained in:
parent
97257c3891
commit
257aa441a1
186
tools/hwsim.c
186
tools/hwsim.c
@ -35,11 +35,12 @@
|
|||||||
|
|
||||||
#include "src/util.h"
|
#include "src/util.h"
|
||||||
#include "src/storage.h"
|
#include "src/storage.h"
|
||||||
#include "src/dbus.h"
|
|
||||||
|
|
||||||
#define HWSIM_RADIO_MANAGER_INTERFACE "net.connman.iwd.hwsim.RadioManager"
|
#define HWSIM_SERVICE "net.connman.iwd.hwsim"
|
||||||
#define HWSIM_RADIO_INTERFACE "net.connman.iwd.hwsim.Radio"
|
|
||||||
#define HWSIM_INTERFACE_INTERFACE "net.connman.iwd.hwsim.Interface"
|
#define HWSIM_RADIO_MANAGER_INTERFACE HWSIM_SERVICE ".RadioManager"
|
||||||
|
#define HWSIM_RADIO_INTERFACE HWSIM_SERVICE ".Radio"
|
||||||
|
#define HWSIM_INTERFACE_INTERFACE HWSIM_SERVICE ".Interface"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HWSIM_CMD_UNSPEC,
|
HWSIM_CMD_UNSPEC,
|
||||||
@ -268,6 +269,9 @@ struct interface_info_rec {
|
|||||||
static struct l_queue *radio_info;
|
static struct l_queue *radio_info;
|
||||||
static struct l_queue *interface_info;
|
static struct l_queue *interface_info;
|
||||||
|
|
||||||
|
static struct l_dbus_message *pending_create_msg;
|
||||||
|
static uint32_t pending_create_radio_id;
|
||||||
|
|
||||||
static void radio_free(void *user_data)
|
static void radio_free(void *user_data)
|
||||||
{
|
{
|
||||||
struct radio_info_rec *rec = user_data;
|
struct radio_info_rec *rec = user_data;
|
||||||
@ -333,6 +337,33 @@ static const char *interface_get_path(const struct interface_info_rec *rec)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *dbus_error_busy(struct l_dbus_message *msg)
|
||||||
|
{
|
||||||
|
return l_dbus_message_new_error(msg, HWSIM_SERVICE ".InProgress",
|
||||||
|
"Operation already in progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *dbus_error_failed(struct l_dbus_message *msg)
|
||||||
|
{
|
||||||
|
return l_dbus_message_new_error(msg, HWSIM_SERVICE ".Failed",
|
||||||
|
"Operation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *dbus_error_invalid_args(
|
||||||
|
struct l_dbus_message *msg)
|
||||||
|
{
|
||||||
|
return l_dbus_message_new_error(msg, HWSIM_SERVICE ".InvalidArgs",
|
||||||
|
"Argument type is wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbus_pending_reply(struct l_dbus_message **msg,
|
||||||
|
struct l_dbus_message *reply)
|
||||||
|
{
|
||||||
|
l_dbus_send(dbus, reply);
|
||||||
|
l_dbus_message_unref(*msg);
|
||||||
|
*msg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static bool parse_addresses(const uint8_t *buf, size_t len,
|
static bool parse_addresses(const uint8_t *buf, size_t len,
|
||||||
struct radio_info_rec *rec)
|
struct radio_info_rec *rec)
|
||||||
{
|
{
|
||||||
@ -546,11 +577,25 @@ static void get_radio_callback(struct l_genl_msg *msg, void *user_data)
|
|||||||
HWSIM_RADIO_INTERFACE, "Name");
|
HWSIM_RADIO_INTERFACE, "Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send pending CreateRadio reply */
|
||||||
|
if (pending_create_msg && pending_create_radio_id == rec->id) {
|
||||||
|
struct l_dbus_message *reply =
|
||||||
|
l_dbus_message_new_method_return(pending_create_msg);
|
||||||
|
|
||||||
|
l_dbus_message_set_arguments(reply, "o", path);
|
||||||
|
|
||||||
|
dbus_pending_reply(&pending_create_msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_free_radio:
|
err_free_radio:
|
||||||
if (!old)
|
if (!old)
|
||||||
radio_free(rec);
|
radio_free(rec);
|
||||||
|
|
||||||
|
if (pending_create_msg && pending_create_radio_id == *id)
|
||||||
|
dbus_pending_reply(&pending_create_msg,
|
||||||
|
dbus_error_failed(pending_create_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_wiphy_callback(struct l_genl_msg *msg, void *user_data)
|
static void get_wiphy_callback(struct l_genl_msg *msg, void *user_data)
|
||||||
@ -855,8 +900,137 @@ static void nl80211_config_notify(struct l_genl_msg *msg, void *user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void radio_manager_create_callback(struct l_genl_msg *msg,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct l_dbus_message *reply;
|
||||||
|
struct l_genl_attr attr;
|
||||||
|
struct radio_info_rec *radio;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the radio id is returned in the error field of
|
||||||
|
* the returned message.
|
||||||
|
*/
|
||||||
|
if (l_genl_attr_init(&attr, msg))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
err = l_genl_msg_get_error(msg);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
pending_create_radio_id = err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the NEW_RADIO event has been received we'll have added the
|
||||||
|
* radio to radio_info already but we can send the method return
|
||||||
|
* only now that we know the ID returned by our command.
|
||||||
|
*/
|
||||||
|
radio = l_queue_find(radio_info, radio_info_match_id,
|
||||||
|
L_UINT_TO_PTR(pending_create_radio_id));
|
||||||
|
if (radio) {
|
||||||
|
const char *path = radio_get_path(radio);
|
||||||
|
|
||||||
|
reply = l_dbus_message_new_method_return(pending_create_msg);
|
||||||
|
|
||||||
|
l_dbus_message_set_arguments(reply, "o", path);
|
||||||
|
|
||||||
|
dbus_pending_reply(&pending_create_msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
reply = dbus_error_failed(pending_create_msg);
|
||||||
|
|
||||||
|
dbus_pending_reply(&pending_create_msg, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *radio_manager_create(struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *new_msg;
|
||||||
|
const char *name;
|
||||||
|
bool p2p;
|
||||||
|
|
||||||
|
if (pending_create_msg)
|
||||||
|
return dbus_error_busy(message);
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(message, "sb", &name, &p2p))
|
||||||
|
return dbus_error_invalid_args(message);
|
||||||
|
|
||||||
|
new_msg = l_genl_msg_new_sized(HWSIM_CMD_NEW_RADIO, 16 + strlen(name));
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(new_msg, HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
if (name[0])
|
||||||
|
l_genl_msg_append_attr(new_msg, HWSIM_ATTR_RADIO_NAME,
|
||||||
|
strlen(name), name);
|
||||||
|
|
||||||
|
if (p2p)
|
||||||
|
l_genl_msg_append_attr(new_msg, HWSIM_ATTR_SUPPORT_P2P_DEVICE,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
l_genl_family_send(hwsim, new_msg, radio_manager_create_callback,
|
||||||
|
pending_create_msg, NULL);
|
||||||
|
|
||||||
|
pending_create_msg = l_dbus_message_ref(message);
|
||||||
|
pending_create_radio_id = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void setup_radio_manager_interface(struct l_dbus_interface *interface)
|
static void setup_radio_manager_interface(struct l_dbus_interface *interface)
|
||||||
{
|
{
|
||||||
|
l_dbus_interface_method(interface, "CreateRadio", 0,
|
||||||
|
radio_manager_create, "o", "sb",
|
||||||
|
"path", "name", "p2p_device");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radio_destroy_callback(struct l_genl_msg *msg, void *user_data)
|
||||||
|
{
|
||||||
|
struct l_dbus_message *message = user_data;
|
||||||
|
struct l_dbus_message *reply;
|
||||||
|
struct l_genl_attr attr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (l_genl_attr_init(&attr, msg))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
err = l_genl_msg_get_error(msg);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
reply = l_dbus_message_new_method_return(message);
|
||||||
|
l_dbus_message_set_arguments(reply, "");
|
||||||
|
|
||||||
|
dbus_pending_reply(&message, reply);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
reply = dbus_error_failed(message);
|
||||||
|
|
||||||
|
dbus_pending_reply(&message, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_dbus_message *radio_destroy(struct l_dbus *dbus,
|
||||||
|
struct l_dbus_message *message,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *del_msg;
|
||||||
|
struct radio_info_rec *radio = user_data;
|
||||||
|
|
||||||
|
del_msg = l_genl_msg_new_sized(HWSIM_CMD_DEL_RADIO, 8);
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(del_msg, HWSIM_ATTR_RADIO_ID, 4, &radio->id);
|
||||||
|
|
||||||
|
l_genl_family_send(hwsim, del_msg, radio_destroy_callback,
|
||||||
|
l_dbus_message_ref(message), NULL);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool radio_property_get_name(struct l_dbus *dbus,
|
static bool radio_property_get_name(struct l_dbus *dbus,
|
||||||
@ -953,6 +1127,8 @@ static bool radio_property_get_regdom(struct l_dbus *dbus,
|
|||||||
|
|
||||||
static void setup_radio_interface(struct l_dbus_interface *interface)
|
static void setup_radio_interface(struct l_dbus_interface *interface)
|
||||||
{
|
{
|
||||||
|
l_dbus_interface_method(interface, "Destroy", 0, radio_destroy, "", "");
|
||||||
|
|
||||||
l_dbus_interface_property(interface, "Name", 0, "s",
|
l_dbus_interface_property(interface, "Name", 0, "s",
|
||||||
radio_property_get_name, NULL);
|
radio_property_get_name, NULL);
|
||||||
l_dbus_interface_property(interface, "Addresses", 0, "s",
|
l_dbus_interface_property(interface, "Addresses", 0, "s",
|
||||||
@ -1386,6 +1562,8 @@ int main(int argc, char *argv[])
|
|||||||
l_genl_family_unref(nl80211);
|
l_genl_family_unref(nl80211);
|
||||||
l_genl_unref(genl);
|
l_genl_unref(genl);
|
||||||
|
|
||||||
|
if (pending_create_msg)
|
||||||
|
l_dbus_message_unref(pending_create_msg);
|
||||||
l_dbus_destroy(dbus);
|
l_dbus_destroy(dbus);
|
||||||
|
|
||||||
hwsim_radio_cache_cleanup();
|
hwsim_radio_cache_cleanup();
|
||||||
|
Loading…
Reference in New Issue
Block a user