1 /*
2 * Copyright (c) 2024 Vogl Electronic GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 #include <zephyr/mgmt/hawkbit/hawkbit.h>
10 #include <zephyr/mgmt/hawkbit/config.h>
11 #include <zephyr/mgmt/hawkbit/autohandler.h>
12
13 LOG_MODULE_DECLARE(hawkbit);
14
15 static void autohandler(struct k_work *work);
16
17 static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle, autohandler);
18 static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle_once, autohandler);
19
20 static K_EVENT_DEFINE(hawkbit_autohandler_event);
21
autohandler(struct k_work * work)22 static void autohandler(struct k_work *work)
23 {
24 k_event_clear(&hawkbit_autohandler_event, UINT32_MAX);
25
26 enum hawkbit_response response = hawkbit_probe();
27
28 k_event_set(&hawkbit_autohandler_event, BIT(response));
29
30 switch (response) {
31 case HAWKBIT_UNCONFIRMED_IMAGE:
32 LOG_ERR("Current image is not confirmed");
33 LOG_ERR("Rebooting to previous confirmed image");
34 LOG_ERR("If this image is flashed using a hardware tool");
35 LOG_ERR("Make sure that it is a confirmed image");
36 hawkbit_reboot();
37 break;
38
39 case HAWKBIT_NO_UPDATE:
40 LOG_INF("No update found");
41 break;
42
43 case HAWKBIT_UPDATE_INSTALLED:
44 LOG_INF("Update installed");
45 hawkbit_reboot();
46 break;
47
48 case HAWKBIT_ALLOC_ERROR:
49 LOG_INF("Memory allocation error");
50 break;
51
52 case HAWKBIT_DOWNLOAD_ERROR:
53 LOG_INF("Update failed");
54 break;
55
56 case HAWKBIT_NETWORKING_ERROR:
57 LOG_INF("Network error");
58 break;
59
60 case HAWKBIT_PERMISSION_ERROR:
61 LOG_INF("Permission error");
62 break;
63
64 case HAWKBIT_METADATA_ERROR:
65 LOG_INF("Metadata error");
66 break;
67
68 case HAWKBIT_NOT_INITIALIZED:
69 LOG_INF("hawkBit not initialized");
70 break;
71
72 case HAWKBIT_PROBE_IN_PROGRESS:
73 LOG_INF("hawkBit is already running");
74 break;
75
76 default:
77 LOG_ERR("Invalid response: %d", response);
78 break;
79 }
80
81 if (k_work_delayable_from_work(work) == &hawkbit_work_handle) {
82 k_work_reschedule(&hawkbit_work_handle, K_SECONDS(hawkbit_get_poll_interval()));
83 }
84 }
85
hawkbit_autohandler_wait(uint32_t events,k_timeout_t timeout)86 enum hawkbit_response hawkbit_autohandler_wait(uint32_t events, k_timeout_t timeout)
87 {
88 uint32_t ret = k_event_wait(&hawkbit_autohandler_event, events, false, timeout);
89
90 for (int i = 1; i < HAWKBIT_PROBE_IN_PROGRESS; i++) {
91 if (ret & BIT(i)) {
92 return i;
93 }
94 }
95 return HAWKBIT_NO_RESPONSE;
96 }
97
hawkbit_autohandler_cancel(void)98 int hawkbit_autohandler_cancel(void)
99 {
100 return k_work_cancel_delayable(&hawkbit_work_handle);
101 }
102
hawkbit_autohandler_set_delay(k_timeout_t timeout,bool if_bigger)103 int hawkbit_autohandler_set_delay(k_timeout_t timeout, bool if_bigger)
104 {
105 if (!if_bigger || timeout.ticks > k_work_delayable_remaining_get(&hawkbit_work_handle)) {
106 hawkbit_autohandler_cancel();
107 LOG_INF("Setting new delay for next run: %02u:%02u:%02u",
108 (uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) / 3600,
109 (uint32_t)((timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 3600) / 60,
110 (uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 60);
111 return k_work_reschedule(&hawkbit_work_handle, timeout);
112 }
113 return 0;
114 }
115
hawkbit_autohandler(bool auto_reschedule)116 void hawkbit_autohandler(bool auto_reschedule)
117 {
118 if (auto_reschedule) {
119 k_work_reschedule(&hawkbit_work_handle, K_NO_WAIT);
120 } else {
121 k_work_reschedule(&hawkbit_work_handle_once, K_NO_WAIT);
122 }
123 }
124