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