1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "iotx_dm_internal.h"
5
6 #if defined(OTA_ENABLED) && !defined(BUILD_AOS)
7
8 static dm_fota_ctx_t g_dm_fota_ctx;
9
dm_fota_get_ctx(void)10 dm_fota_ctx_t *dm_fota_get_ctx(void)
11 {
12 return &g_dm_fota_ctx;
13 }
14
dm_fota_init(void)15 int dm_fota_init(void)
16 {
17 dm_fota_ctx_t *ctx = dm_fota_get_ctx();
18
19 memset(ctx, 0, sizeof(dm_fota_ctx_t));
20
21 return SUCCESS_RETURN;
22 }
23
dm_fota_deinit(void)24 int dm_fota_deinit(void)
25 {
26 dm_fota_ctx_t *ctx = dm_fota_get_ctx();
27
28 memset(ctx, 0, sizeof(dm_fota_ctx_t));
29
30 return SUCCESS_RETURN;
31 }
32
_dm_fota_send_new_config_to_user(void * ota_handle)33 static int _dm_fota_send_new_config_to_user(void *ota_handle)
34 {
35 int res = 0, message_len = 0;
36 char *message = NULL;
37 char version[128] = { 0 };
38 const char *fota_new_config_fmt = "{\"version\":\"%s\"}";
39
40 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_VERSION, version, 128);
41
42 message_len = strlen(fota_new_config_fmt) + strlen(version) + 1;
43
44 message = DM_malloc(message_len);
45 if (message == NULL) {
46 return DM_MEMORY_NOT_ENOUGH;
47 }
48 memset(message, 0, message_len);
49 HAL_Snprintf(message, message_len, fota_new_config_fmt, version);
50
51 dm_log_info("Send To User: %s", message);
52
53 res = _dm_msg_send_to_user(IOTX_DM_EVENT_FOTA_NEW_FIRMWARE, message);
54 if (res != SUCCESS_RETURN) {
55 if (message) {
56 DM_free(message);
57 }
58 return FAIL_RETURN;
59 }
60
61 return SUCCESS_RETURN;
62 }
63
dm_fota_perform_sync(_OU_ char * output,_IN_ int output_len)64 int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len)
65 {
66 int res = 0, file_download = 0, retry_timeout = 0, retry_max_timeout = 0;
67 uint32_t file_size = 0, file_downloaded = 0;
68 uint32_t percent_pre = 0, percent_now = 0;
69 unsigned long long report_pre = 0, report_now = 0;
70 dm_fota_ctx_t *ctx = dm_fota_get_ctx();
71 void *ota_handle = NULL;
72 uint32_t ota_type = IOT_OTAT_NONE;
73 int ret = 0;
74
75 if (output == NULL || output_len <= 0) {
76 return DM_INVALID_PARAMETER;
77 }
78
79 /* Get Ota Handle */
80 res = dm_ota_get_ota_handle(&ota_handle);
81 if (res != SUCCESS_RETURN) {
82 return FAIL_RETURN;
83 }
84
85 if (ota_handle == NULL) {
86 return FAIL_RETURN;
87 }
88 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
89
90 if (ota_type != IOT_OTAT_FOTA) {
91 return FAIL_RETURN;
92 }
93
94 /* reset the size_fetched in ota_handle to be 0 */
95 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
96 /* Prepare Write Data To Storage */
97 HAL_Firmware_Persistence_Start();
98 while (1) {
99 file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
100 if (file_download < 0) {
101 res = dm_opt_get(DM_OPT_FOTA_RETRY_TIMEOUT_MS, &retry_max_timeout);
102 if (res == SUCCESS_RETURN && retry_timeout >= retry_max_timeout) {
103 IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
104 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_STATE, NULL, 0);
105 HAL_Firmware_Persistence_Stop();
106 ctx->is_report_new_config = 0;
107 return FAIL_RETURN;
108 }
109 retry_timeout += CONFIG_FOTA_RETRY_INTERNAL_MS;
110 HAL_SleepMs(CONFIG_FOTA_RETRY_INTERNAL_MS);
111 dm_log_err("IOT_OTA_FetchYield next time");
112 continue;
113 }
114 retry_timeout = 0;
115
116 /* Write Config File Into Stroage */
117 ret = HAL_Firmware_Persistence_Write(output, file_download);
118 if (-1 == ret) {
119 IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_BURN_FAILED, NULL);
120 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_STATE, NULL, 0);
121 dm_log_err("Fota write firmware failed");
122 HAL_Firmware_Persistence_Stop();
123 ctx->is_report_new_config = 0;
124 return FAIL_RETURN;
125 }
126
127 /* Get OTA information */
128 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
129 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
130
131 /* Calculate Download Percent And Update Report Timestamp*/
132 percent_now = (file_downloaded * 100) / file_size;
133 report_now = HAL_UptimeMs();
134
135 /* Report Download Process To Cloud */
136 if (report_now < report_pre) {
137 report_pre = report_now;
138 }
139 if ((((percent_now - percent_pre) > 5) &&
140 ((report_now - report_pre) > 50)) ||
141 (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
142 IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
143 percent_pre = percent_now;
144 report_pre = report_now;
145 }
146
147 /* Check If OTA Finished */
148 if (IOT_OTA_IsFetchFinish(ota_handle)) {
149 uint32_t file_isvalid = 0;
150 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_FIRMWARE, &file_isvalid,
151 4);
152 if (file_isvalid == 0) {
153 IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_CHECK_FALIED, NULL);
154 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_STATE, NULL, 0);
155 HAL_Firmware_Persistence_Stop();
156 ctx->is_report_new_config = 0;
157 return FAIL_RETURN;
158 } else {
159 break;
160 }
161 }
162 }
163
164 HAL_Firmware_Persistence_Stop();
165 ctx->is_report_new_config = 0;
166
167 return SUCCESS_RETURN;
168 }
169
dm_fota_status_check(void)170 int dm_fota_status_check(void)
171 {
172 int res = 0;
173 dm_fota_ctx_t *ctx = dm_fota_get_ctx();
174 void *ota_handle = NULL;
175
176 /* Get Ota Handle */
177 res = dm_ota_get_ota_handle(&ota_handle);
178 if (res != SUCCESS_RETURN) {
179 return FAIL_RETURN;
180 }
181
182 if (IOT_OTA_IsFetching(ota_handle)) {
183 uint32_t ota_type = IOT_OTAT_NONE;
184
185 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
186
187 if (ota_type == IOT_OTAT_FOTA) {
188 /* Send New Config Information To User */
189 if (ctx->is_report_new_config == 0) {
190 dm_log_debug("Fota Status Check");
191 res = _dm_fota_send_new_config_to_user(ota_handle);
192 if (res == SUCCESS_RETURN) {
193 ctx->is_report_new_config = 1;
194 }
195 }
196 }
197 }
198
199 return SUCCESS_RETURN;
200 }
201
dm_fota_request_image(const char * version,int buffer_len)202 int dm_fota_request_image(const char *version, int buffer_len)
203 {
204 int res = 0;
205 void *ota_handle = NULL;
206 char *version_str = NULL;
207
208 if (NULL == version || buffer_len <= 0) {
209 dm_log_info("invalid input");
210 return FAIL_RETURN;
211 }
212
213 /* Get Ota Handle */
214 res = dm_ota_get_ota_handle(&ota_handle);
215 if (res != SUCCESS_RETURN) {
216 return FAIL_RETURN;
217 }
218
219 version_str = DM_malloc(buffer_len + 1);
220 if (NULL == version_str) {
221 dm_log_info("failed to malloc");
222 return FAIL_RETURN;
223 }
224 memset(version_str, 0, buffer_len + 1);
225 memcpy(version_str, version, buffer_len);
226
227 res = iotx_req_image(ota_handle, version_str);
228 DM_free(version_str);
229 return res;
230 }
231
232 #endif
233