257 lines
4.6 KiB
C
257 lines
4.6 KiB
C
/*
|
|
* 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 "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);
|
|
}
|
|
}
|
|
}
|