1 /*
2  * Copyright (c) 2022 grandcentrix GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "common.h"
8 
9 #include <errno.h>
10 #include <stdio.h>
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/net/mqtt_sn.h>
14 #include <zephyr/net/conn_mgr_monitor.h>
15 #include <zephyr/net/net_mgmt.h>
16 #include <zephyr/net/socket.h>
17 
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(mqtt_sn_publisher_sample, LOG_LEVEL_INF);
20 
21 #if defined(CONFIG_USERSPACE)
22 #include <zephyr/app_memory/app_memdomain.h>
23 K_APPMEM_PARTITION_DEFINE(app_partition);
24 struct k_mem_domain app_domain;
25 #endif
26 
27 #define APP_BANNER "MQTT-SN sample"
28 
29 K_SEM_DEFINE(run_app, 0, 1);
30 
31 #define EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
32 
net_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)33 static void net_event_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
34 			      struct net_if *iface)
35 {
36 	if ((mgmt_event & EVENT_MASK) != mgmt_event) {
37 		return;
38 	}
39 
40 	if (mgmt_event == NET_EVENT_L4_CONNECTED) {
41 		LOG_INF("Network connected");
42 
43 		k_sem_give(&run_app);
44 
45 		return;
46 	}
47 
48 	if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
49 		LOG_INF("Network disconnected");
50 
51 		k_sem_reset(&run_app);
52 
53 		return;
54 	}
55 }
56 
init_app(void)57 static void init_app(void)
58 {
59 	static struct net_mgmt_event_callback mgmt_cb;
60 
61 	LOG_INF(APP_BANNER);
62 
63 #if defined(CONFIG_USERSPACE)
64 	int err;
65 	struct k_mem_partition *parts[] = {
66 #if Z_LIBC_PARTITION_EXISTS
67 		&z_libc_partition,
68 #endif
69 		&app_partition
70 	};
71 
72 	err = k_mem_domain_init(&app_domain, ARRAY_SIZE(parts), parts);
73 	__ASSERT(err == 0, "k_mem_domain_init() failed %d", err);
74 	ARG_UNUSED(err);
75 
76 #endif
77 
78 	if (IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
79 		net_mgmt_init_event_callback(&mgmt_cb, net_event_handler, EVENT_MASK);
80 		net_mgmt_add_event_callback(&mgmt_cb);
81 
82 		conn_mgr_mon_resend_status();
83 	}
84 }
85 
start_client(void * p1,void * p2,void * p3)86 static void start_client(void *p1, void *p2, void *p3)
87 {
88 	ARG_UNUSED(p1);
89 	ARG_UNUSED(p2);
90 	ARG_UNUSED(p3);
91 
92 	/* Wait for connection */
93 	k_sem_take(&run_app, K_FOREVER);
94 
95 	start_thread();
96 }
97 
main(void)98 int main(void)
99 {
100 	init_app();
101 
102 	if (!IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
103 		/* If the config library has not been configured to start the
104 		 * app only after we have a connection, then we can start
105 		 * it right away.
106 		 */
107 		k_sem_give(&run_app);
108 	}
109 
110 #if defined(CONFIG_USERSPACE)
111 	k_thread_access_grant(k_current_get(), &run_app);
112 	k_mem_domain_add_thread(&app_domain, k_current_get());
113 
114 	k_thread_user_mode_enter(start_client, NULL, NULL, NULL);
115 #else
116 	start_client(NULL, NULL, NULL);
117 #endif
118 	return 0;
119 }
120