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