blob: 8fae71acec1740f1e38c5d674e04be353b3e8e5e [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(conn_mgr_conn, CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL);
#include <zephyr/net/net_if.h>
#include <zephyr/net/conn_mgr_connectivity.h>
#include <zephyr/sys/iterable_sections.h>
#include "conn_mgr_private.h"
int conn_mgr_if_connect(struct net_if *iface)
{
struct conn_mgr_conn_binding *binding;
struct conn_mgr_conn_api *api;
int status;
LOG_DBG("iface %p connect", iface);
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return -ENOTSUP;
}
api = binding->impl->api;
if (!api->connect) {
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
if (!net_if_is_admin_up(iface)) {
status = net_if_up(iface);
if (status) {
goto out;
}
}
status = api->connect(binding);
out:
k_mutex_unlock(binding->mutex);
return status;
}
int conn_mgr_if_disconnect(struct net_if *iface)
{
struct conn_mgr_conn_binding *binding;
struct conn_mgr_conn_api *api;
int status = 0;
LOG_DBG("iface %p disconnect", iface);
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return -ENOTSUP;
}
api = binding->impl->api;
if (!api->disconnect) {
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
if (!net_if_is_admin_up(iface)) {
goto out;
}
status = api->disconnect(binding);
out:
k_mutex_unlock(binding->mutex);
return status;
}
bool conn_mgr_if_is_bound(struct net_if *iface)
{
struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);
return binding != NULL;
}
int conn_mgr_if_get_opt(struct net_if *iface, int optname, void *optval, size_t *optlen)
{
struct conn_mgr_conn_binding *binding;
struct conn_mgr_conn_api *api;
int status;
if (!optlen) {
return -EINVAL;
}
if (!optval) {
*optlen = 0;
return -EINVAL;
}
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
*optlen = 0;
return -ENOTSUP;
}
api = binding->impl->api;
if (!api->get_opt) {
*optlen = 0;
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
status = api->get_opt(binding, optname, optval, optlen);
k_mutex_unlock(binding->mutex);
return status;
}
int conn_mgr_if_set_opt(struct net_if *iface, int optname, const void *optval, size_t optlen)
{
struct conn_mgr_conn_binding *binding;
struct conn_mgr_conn_api *api;
int status;
if (!optval) {
return -EINVAL;
}
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return -ENOTSUP;
}
api = binding->impl->api;
if (!api->set_opt) {
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
status = api->set_opt(binding, optname, optval, optlen);
k_mutex_unlock(binding->mutex);
return status;
}
int conn_mgr_if_set_flag(struct net_if *iface, enum conn_mgr_if_flag flag, bool value)
{
struct conn_mgr_conn_binding *binding;
if (flag >= CONN_MGR_NUM_IF_FLAGS) {
return -EINVAL;
}
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
binding->flags &= ~BIT(flag);
if (value) {
binding->flags |= BIT(flag);
}
k_mutex_unlock(binding->mutex);
return 0;
}
bool conn_mgr_if_get_flag(struct net_if *iface, enum conn_mgr_if_flag flag)
{
struct conn_mgr_conn_binding *binding;
bool value;
if (flag >= CONN_MGR_NUM_IF_FLAGS) {
return false;
}
binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return false;
}
k_mutex_lock(binding->mutex, K_FOREVER);
value = !!(binding->flags & BIT(flag));
k_mutex_unlock(binding->mutex);
return value;
}
int conn_mgr_if_get_timeout(struct net_if *iface)
{
struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);
int value;
if (!binding) {
return false;
}
k_mutex_lock(binding->mutex, K_FOREVER);
value = binding->timeout;
k_mutex_unlock(binding->mutex);
return value;
}
int conn_mgr_if_set_timeout(struct net_if *iface, int timeout)
{
struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);
if (!binding) {
return -ENOTSUP;
}
k_mutex_lock(binding->mutex, K_FOREVER);
binding->timeout = timeout;
k_mutex_unlock(binding->mutex);
return 0;
}
void conn_mgr_conn_init(void)
{
STRUCT_SECTION_FOREACH(conn_mgr_conn_binding, binding) {
if (!(binding->impl->api)) {
LOG_ERR("Connectivity implementation has NULL API, and will be treated as "
"non-existent.");
} else if (binding->impl->api->init) {
k_mutex_lock(binding->mutex, K_FOREVER);
/* Set initial default values for binding state */
binding->timeout = CONN_MGR_IF_NO_TIMEOUT;
/* Call binding initializer */
binding->impl->api->init(binding);
k_mutex_unlock(binding->mutex);
}
}
}