ota_client.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /*
  2. * Tencent is pleased to support the open source community by making IoT Hub
  3. available.
  4. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  5. * Licensed under the MIT License (the "License"); you may not use this file
  6. except in
  7. * compliance with the License. You may obtain a copy of the License at
  8. * http://opensource.org/licenses/MIT
  9. * Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is
  11. * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. KIND,
  13. * either express or implied. See the License for the specific language
  14. governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. #include "ota_client.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "ota_fetch.h"
  26. #include "ota_lib.h"
  27. #include "qcloud_iot_export.h"
  28. #include "utils_param_check.h"
  29. #include "utils_timer.h"
  30. #define OTA_VERSION_STR_LEN_MIN (1)
  31. #define OTA_VERSION_STR_LEN_MAX (32)
  32. typedef struct {
  33. unsigned char profile_idx;
  34. const char *product_id; /* point to product id */
  35. const char *device_name; /* point to device name */
  36. uint32_t id; /* message id */
  37. IOT_OTA_State_Code state; /* OTA state */
  38. uint32_t size_last_fetched; /* size of last downloaded */
  39. uint32_t size_fetched; /* size of already downloaded */
  40. uint32_t size_file; /* size of file */
  41. char *purl; /* point to URL */
  42. char *version; /* point to string */
  43. char md5sum[33]; /* MD5 string */
  44. void *md5; /* MD5 handle */
  45. void *ch_signal; /* channel handle of signal exchanged with OTA server */
  46. void *ch_fetch; /* channel handle of download */
  47. int err; /* last error code */
  48. short current_signal_type;
  49. Timer report_timer;
  50. } OTA_Struct_t;
  51. /* check ota progress */
  52. /* return: true, valid progress state; false, invalid progress state. */
  53. static int _ota_check_progress(IOT_OTA_Progress_Code progress)
  54. {
  55. return ((progress >= IOT_OTAP_BURN_FAILED) && (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX));
  56. }
  57. /* callback when OTA topic msg is received */
  58. static void _ota_callback(void *pcontext, const char *msg, uint32_t msg_len)
  59. {
  60. #define OTA_JSON_TYPE_VALUE_LENGTH 64
  61. char *json_type = NULL;
  62. OTA_Struct_t *h_ota = (OTA_Struct_t *)pcontext;
  63. if (h_ota->state >= IOT_OTAS_FETCHING) {
  64. Log_i("In downloading or downloaded state");
  65. goto End;
  66. }
  67. if (msg == NULL || msg_len <= 0) {
  68. Log_e("OTA response message is NULL");
  69. return;
  70. }
  71. if (qcloud_otalib_get_firmware_type(msg, &json_type) != QCLOUD_RET_SUCCESS) {
  72. Log_e("Get firmware type failed!");
  73. goto End;
  74. }
  75. if (!strcmp(json_type, REPORT_VERSION_RSP)) {
  76. if (qcloud_otalib_get_report_version_result(msg) < QCLOUD_RET_SUCCESS) {
  77. Log_e("Report version failed!");
  78. h_ota->err = IOT_OTA_ERR_REPORT_VERSION;
  79. h_ota->state = IOT_OTAS_FETCHED;
  80. } else {
  81. Log_i("Report version success!");
  82. }
  83. goto End;
  84. } else {
  85. if (strcmp(json_type, UPDATE_FIRMWARE) != 0) {
  86. Log_e("Netheir Report version result nor update firmware! type: %s", json_type);
  87. goto End;
  88. }
  89. if (NULL != json_type) {
  90. HAL_Free(json_type);
  91. json_type = NULL;
  92. }
  93. if (0 != qcloud_otalib_get_params(msg, &json_type, &h_ota->purl, &h_ota->version, h_ota->md5sum,
  94. &h_ota->size_file)) {
  95. Log_e("Get firmware parameter failed");
  96. goto End;
  97. }
  98. h_ota->state = IOT_OTAS_FETCHING;
  99. }
  100. End:
  101. if (json_type != NULL)
  102. HAL_Free(json_type);
  103. #undef OTA_JSON_TYPE_VALUE_LENGTH
  104. }
  105. static void IOT_OTA_ResetStatus(void *handle)
  106. {
  107. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  108. Log_i("reset OTA state!");
  109. h_ota->state = IOT_OTAS_INITED;
  110. h_ota->err = 0;
  111. if (NULL != h_ota->purl) {
  112. HAL_Free(h_ota->purl);
  113. h_ota->purl = NULL;
  114. }
  115. if (NULL != h_ota->version) {
  116. HAL_Free(h_ota->version);
  117. h_ota->version = NULL;
  118. }
  119. }
  120. static int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_Code progress, IOT_OTAReportType reportType)
  121. {
  122. #define MSG_REPORT_LEN (256)
  123. int ret = QCLOUD_ERR_FAILURE;
  124. char * msg_reported;
  125. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  126. if (NULL == handle) {
  127. Log_e("handle is NULL");
  128. return IOT_OTA_ERR_INVALID_PARAM;
  129. }
  130. if (IOT_OTAS_UNINITED == h_ota->state) {
  131. Log_e("handle is uninitialized");
  132. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  133. return QCLOUD_ERR_FAILURE;
  134. }
  135. if (!_ota_check_progress(progress)) {
  136. Log_e("progress is a invalid parameter");
  137. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  138. return QCLOUD_ERR_FAILURE;
  139. }
  140. if (NULL == (msg_reported = HAL_Malloc(MSG_REPORT_LEN))) {
  141. Log_e("allocate for msg_reported failed");
  142. h_ota->err = IOT_OTA_ERR_NOMEM;
  143. return QCLOUD_ERR_FAILURE;
  144. }
  145. ret = qcloud_otalib_gen_report_msg(msg_reported, MSG_REPORT_LEN, h_ota->id, h_ota->version, progress, reportType);
  146. if (0 != ret) {
  147. Log_e("generate reported message failed");
  148. h_ota->err = ret;
  149. goto do_exit;
  150. }
  151. ret = qcloud_osc_report_progress(h_ota->ch_signal, msg_reported);
  152. if (QCLOUD_RET_SUCCESS != ret) {
  153. Log_e("Report progress failed");
  154. h_ota->err = ret;
  155. goto do_exit;
  156. }
  157. ret = QCLOUD_RET_SUCCESS;
  158. do_exit:
  159. if (NULL != msg_reported) {
  160. HAL_Free(msg_reported);
  161. }
  162. return ret;
  163. #undef MSG_REPORT_LEN
  164. }
  165. static int IOT_OTA_ReportUpgradeResult(void *handle, const char *version, IOT_OTAReportType reportType)
  166. {
  167. #define MSG_UPGPGRADE_LEN (256)
  168. POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
  169. POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM);
  170. int ret, len;
  171. char * msg_upgrade;
  172. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  173. if (IOT_OTAS_UNINITED == h_ota->state) {
  174. Log_e("handle is uninitialized");
  175. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  176. return QCLOUD_ERR_FAILURE;
  177. }
  178. len = strlen(version);
  179. if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
  180. Log_e("version string is invalid: must be [1, 32] chars");
  181. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  182. return QCLOUD_ERR_FAILURE;
  183. }
  184. if (NULL == (msg_upgrade = HAL_Malloc(MSG_UPGPGRADE_LEN))) {
  185. Log_e("allocate for msg_informed failed");
  186. h_ota->err = IOT_OTA_ERR_NOMEM;
  187. return QCLOUD_ERR_FAILURE;
  188. }
  189. ret = qcloud_otalib_gen_report_msg(msg_upgrade, MSG_UPGPGRADE_LEN, 1, version, 1, reportType);
  190. if (ret != 0) {
  191. Log_e("generate inform message failed");
  192. h_ota->err = ret;
  193. ret = QCLOUD_ERR_FAILURE;
  194. goto do_exit;
  195. }
  196. ret = qcloud_osc_report_upgrade_result(h_ota->ch_signal, msg_upgrade);
  197. if (0 > ret) {
  198. Log_e("Report version failed");
  199. h_ota->err = ret;
  200. ret = QCLOUD_ERR_FAILURE;
  201. goto do_exit;
  202. }
  203. if ((IOT_OTAR_UPGRADE_FAIL == reportType) || (IOT_OTAR_UPGRADE_SUCCESS == reportType) ||
  204. (IOT_OTAR_MD5_NOT_MATCH == reportType)) {
  205. IOT_OTA_ResetStatus(h_ota);
  206. }
  207. do_exit:
  208. if (NULL != msg_upgrade) {
  209. HAL_Free(msg_upgrade);
  210. }
  211. return ret;
  212. #undef MSG_UPGPGRADE_LEN
  213. }
  214. /* Init OTA handle */
  215. void *IOT_OTA_Init(unsigned char profile_idx, const char *product_id, const char *device_name, void *ch_signal)
  216. {
  217. POINTER_SANITY_CHECK(product_id, NULL);
  218. POINTER_SANITY_CHECK(device_name, NULL);
  219. POINTER_SANITY_CHECK(ch_signal, NULL);
  220. OTA_Struct_t *h_ota = NULL;
  221. if (NULL == (h_ota = HAL_Malloc(sizeof(OTA_Struct_t)))) {
  222. Log_e("allocate failed");
  223. return NULL;
  224. }
  225. memset(h_ota, 0, sizeof(OTA_Struct_t));
  226. h_ota->state = IOT_OTAS_UNINITED;
  227. h_ota->ch_signal = qcloud_osc_init(product_id, device_name, ch_signal, _ota_callback, h_ota);
  228. if (NULL == h_ota->ch_signal) {
  229. Log_e("initialize signal channel failed");
  230. goto do_exit;
  231. }
  232. h_ota->md5 = qcloud_otalib_md5_init();
  233. if (NULL == h_ota->md5) {
  234. Log_e("initialize md5 failed");
  235. goto do_exit;
  236. }
  237. h_ota->profile_idx = profile_idx;
  238. h_ota->product_id = product_id;
  239. h_ota->device_name = device_name;
  240. h_ota->state = IOT_OTAS_INITED;
  241. #ifdef OTA_MQTT_CHANNEL
  242. h_ota->current_signal_type = MQTT_CHANNEL;
  243. #else
  244. h_ota->current_signal_type = COAP_CHANNEL;
  245. #endif
  246. return h_ota;
  247. do_exit:
  248. if (NULL != h_ota->ch_signal) {
  249. qcloud_osc_deinit(h_ota->ch_signal);
  250. }
  251. if (NULL != h_ota->md5) {
  252. qcloud_otalib_md5_deinit(h_ota->md5);
  253. }
  254. if (NULL != h_ota) {
  255. HAL_Free(h_ota);
  256. }
  257. return NULL;
  258. #undef AOM_INFO_MSG_LEN
  259. }
  260. /* Destroy OTA handle and resource */
  261. int IOT_OTA_Destroy(void *handle)
  262. {
  263. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  264. if (NULL == h_ota) {
  265. Log_e("handle is NULL");
  266. return IOT_OTA_ERR_INVALID_PARAM;
  267. }
  268. if (IOT_OTAS_UNINITED == h_ota->state) {
  269. Log_e("handle is uninitialized");
  270. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  271. return QCLOUD_ERR_FAILURE;
  272. }
  273. qcloud_osc_deinit(h_ota->ch_signal);
  274. qcloud_ofc_deinit(h_ota->ch_fetch);
  275. qcloud_otalib_md5_deinit(h_ota->md5);
  276. if (NULL != h_ota->purl) {
  277. HAL_Free(h_ota->purl);
  278. h_ota->purl = NULL;
  279. }
  280. if (NULL != h_ota->version) {
  281. HAL_Free(h_ota->version);
  282. h_ota->version = NULL;
  283. }
  284. HAL_Free(h_ota);
  285. return QCLOUD_RET_SUCCESS;
  286. }
  287. /*support continuous transmission of breakpoints*/
  288. int IOT_OTA_StartDownload(void *handle, uint32_t offset, uint32_t size)
  289. {
  290. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  291. int Ret;
  292. Log_d("to download FW from offset: %u, size: %u", offset, size);
  293. h_ota->size_fetched = offset;
  294. // reset md5 for new download
  295. if (offset == 0) {
  296. Ret = IOT_OTA_ResetClientMD5(h_ota);
  297. if (Ret) {
  298. Log_e("initialize md5 failed");
  299. return QCLOUD_ERR_FAILURE;
  300. }
  301. }
  302. // reinit ofc
  303. qcloud_ofc_deinit(h_ota->ch_fetch);
  304. h_ota->ch_fetch = ofc_Init(h_ota->profile_idx, h_ota->purl, offset, size);
  305. if (NULL == h_ota->ch_fetch) {
  306. Log_e("Initialize fetch module failed");
  307. return QCLOUD_ERR_FAILURE;
  308. }
  309. Ret = qcloud_ofc_connect(h_ota->ch_fetch);
  310. if (QCLOUD_RET_SUCCESS != Ret) {
  311. Log_e("Connect fetch module failed");
  312. h_ota->state = IOT_OTAS_DISCONNECTED;
  313. }
  314. return Ret;
  315. }
  316. /*support continuous transmission of breakpoints*/
  317. void IOT_OTA_UpdateClientMd5(void *handle, char *buff, uint32_t size)
  318. {
  319. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  320. qcloud_otalib_md5_update(h_ota->md5, buff, size);
  321. }
  322. /*support continuous transmission of breakpoints*/
  323. int IOT_OTA_ResetClientMD5(void *handle)
  324. {
  325. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  326. qcloud_otalib_md5_deinit(h_ota->md5);
  327. h_ota->md5 = qcloud_otalib_md5_init();
  328. if (NULL == h_ota->md5) {
  329. return QCLOUD_ERR_FAILURE;
  330. }
  331. return QCLOUD_RET_SUCCESS;
  332. }
  333. int IOT_OTA_ReportVersion(void *handle, const char *version)
  334. {
  335. #define MSG_INFORM_LEN (128)
  336. int ret, len;
  337. char * msg_informed;
  338. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  339. POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
  340. POINTER_SANITY_CHECK(version, IOT_OTA_ERR_INVALID_PARAM);
  341. len = strlen(version);
  342. if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
  343. Log_e("version string is invalid: must be [1, 32] chars");
  344. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  345. return QCLOUD_ERR_FAILURE;
  346. }
  347. if (IOT_OTAS_UNINITED == h_ota->state) {
  348. Log_e("handle is uninitialized");
  349. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  350. return QCLOUD_ERR_FAILURE;
  351. }
  352. IOT_OTA_ResetStatus(h_ota);
  353. if (NULL == (msg_informed = HAL_Malloc(MSG_INFORM_LEN))) {
  354. Log_e("allocate for msg_informed failed");
  355. h_ota->err = IOT_OTA_ERR_NOMEM;
  356. return QCLOUD_ERR_FAILURE;
  357. }
  358. ret = qcloud_otalib_gen_info_msg(msg_informed, MSG_INFORM_LEN, h_ota->id, version);
  359. if (ret != 0) {
  360. Log_e("generate inform message failed");
  361. h_ota->err = ret;
  362. ret = QCLOUD_ERR_FAILURE;
  363. goto do_exit;
  364. }
  365. ret = qcloud_osc_report_version(h_ota->ch_signal, msg_informed);
  366. if (0 > ret) {
  367. Log_e("Report version failed");
  368. h_ota->err = ret;
  369. ret = QCLOUD_ERR_FAILURE;
  370. goto do_exit;
  371. }
  372. do_exit:
  373. if (NULL != msg_informed) {
  374. HAL_Free(msg_informed);
  375. }
  376. return ret;
  377. #undef MSG_INFORM_LEN
  378. }
  379. int IOT_OTA_ReportUpgradeBegin(void *handle)
  380. {
  381. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  382. return IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_BEGIN);
  383. }
  384. int IOT_OTA_ReportUpgradeSuccess(void *handle, const char *version)
  385. {
  386. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  387. int ret;
  388. if (NULL == version) {
  389. ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_SUCCESS);
  390. } else {
  391. ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_SUCCESS);
  392. }
  393. return ret;
  394. }
  395. int IOT_OTA_ReportUpgradeFail(void *handle, const char *version)
  396. {
  397. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  398. int ret;
  399. if (NULL == version) {
  400. ret = IOT_OTA_ReportUpgradeResult(handle, h_ota->version, IOT_OTAR_UPGRADE_FAIL);
  401. } else {
  402. ret = IOT_OTA_ReportUpgradeResult(handle, version, IOT_OTAR_UPGRADE_FAIL);
  403. }
  404. return ret;
  405. }
  406. /* check whether is downloading */
  407. int IOT_OTA_IsFetching(void *handle)
  408. {
  409. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  410. if (NULL == handle) {
  411. Log_e("handle is NULL");
  412. return 0;
  413. }
  414. if (IOT_OTAS_UNINITED == h_ota->state) {
  415. Log_e("handle is uninitialized");
  416. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  417. return 0;
  418. }
  419. return (IOT_OTAS_FETCHING == h_ota->state);
  420. }
  421. /* check whether fetch over */
  422. int IOT_OTA_IsFetchFinish(void *handle)
  423. {
  424. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  425. if (NULL == handle) {
  426. Log_e("handle is NULL");
  427. return 0;
  428. }
  429. if (IOT_OTAS_UNINITED == h_ota->state) {
  430. Log_e("handle is uninitialized");
  431. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  432. return 0;
  433. }
  434. return (IOT_OTAS_FETCHED == h_ota->state);
  435. }
  436. int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_ms)
  437. {
  438. int ret;
  439. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  440. POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
  441. POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM);
  442. NUMBERIC_SANITY_CHECK(buf_len, IOT_OTA_ERR_INVALID_PARAM);
  443. if (IOT_OTAS_FETCHING != h_ota->state) {
  444. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  445. return IOT_OTA_ERR_INVALID_STATE;
  446. }
  447. ret = qcloud_ofc_fetch(h_ota->ch_fetch, buf, buf_len, timeout_ms);
  448. if (ret < 0) {
  449. h_ota->state = IOT_OTAS_FETCHED;
  450. h_ota->err = IOT_OTA_ERR_FETCH_FAILED;
  451. if (ret == IOT_OTA_ERR_FETCH_AUTH_FAIL) { // OTA auth failed
  452. IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_AUTH_FAIL);
  453. h_ota->err = ret;
  454. } else if (ret == IOT_OTA_ERR_FETCH_NOT_EXIST) { // fetch not existed
  455. IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_FILE_NOT_EXIST);
  456. h_ota->err = ret;
  457. } else if (ret == IOT_OTA_ERR_FETCH_TIMEOUT) { // fetch timeout
  458. IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_DOWNLOAD_TIMEOUT);
  459. h_ota->err = ret;
  460. }
  461. return ret;
  462. } else if (0 == h_ota->size_fetched) {
  463. /* force report status in the first */
  464. IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_PERCENTAGE_MIN, IOT_OTAR_DOWNLOAD_BEGIN);
  465. InitTimer(&h_ota->report_timer);
  466. countdown(&h_ota->report_timer, 1);
  467. }
  468. h_ota->size_last_fetched = ret;
  469. h_ota->size_fetched += ret;
  470. /* report percent every second. */
  471. uint32_t percent = (h_ota->size_fetched * 100) / h_ota->size_file;
  472. if (percent == 100) {
  473. IOT_OTA_ReportProgress(h_ota, percent, IOT_OTAR_DOWNLOADING);
  474. } else if (h_ota->size_last_fetched > 0 && expired(&h_ota->report_timer)) {
  475. IOT_OTA_ReportProgress(h_ota, percent, IOT_OTAR_DOWNLOADING);
  476. countdown(&h_ota->report_timer, 1);
  477. }
  478. if (h_ota->size_fetched >= h_ota->size_file) {
  479. h_ota->state = IOT_OTAS_FETCHED;
  480. }
  481. qcloud_otalib_md5_update(h_ota->md5, buf, ret);
  482. return ret;
  483. }
  484. int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len)
  485. {
  486. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  487. POINTER_SANITY_CHECK(handle, IOT_OTA_ERR_INVALID_PARAM);
  488. POINTER_SANITY_CHECK(buf, IOT_OTA_ERR_INVALID_PARAM);
  489. NUMBERIC_SANITY_CHECK(buf_len, IOT_OTA_ERR_INVALID_PARAM);
  490. if (h_ota->state < IOT_OTAS_FETCHING) {
  491. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  492. return IOT_OTA_ERR_INVALID_STATE;
  493. }
  494. switch (type) {
  495. case IOT_OTAG_FETCHED_SIZE:
  496. if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
  497. Log_e("Invalid parameter");
  498. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  499. return QCLOUD_ERR_FAILURE;
  500. } else {
  501. *((uint32_t *)buf) = h_ota->size_fetched;
  502. return 0;
  503. }
  504. case IOT_OTAG_FILE_SIZE:
  505. if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
  506. Log_e("Invalid parameter");
  507. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  508. return QCLOUD_ERR_FAILURE;
  509. } else {
  510. *((uint32_t *)buf) = h_ota->size_file;
  511. return 0;
  512. }
  513. case IOT_OTAG_VERSION:
  514. strncpy(buf, h_ota->version, buf_len);
  515. ((char *)buf)[buf_len - 1] = '\0';
  516. break;
  517. case IOT_OTAG_MD5SUM:
  518. strncpy(buf, h_ota->md5sum, buf_len);
  519. ((char *)buf)[buf_len - 1] = '\0';
  520. break;
  521. case IOT_OTAG_CHECK_FIRMWARE:
  522. if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
  523. Log_e("Invalid parameter");
  524. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  525. return QCLOUD_ERR_FAILURE;
  526. } else if (h_ota->state != IOT_OTAS_FETCHED) {
  527. h_ota->err = IOT_OTA_ERR_INVALID_STATE;
  528. Log_e("Firmware can be checked in IOT_OTAS_FETCHED state only");
  529. return QCLOUD_ERR_FAILURE;
  530. } else {
  531. char md5_str[33];
  532. qcloud_otalib_md5_finalize(h_ota->md5, md5_str);
  533. Log_d("origin=%s, now=%s", h_ota->md5sum, md5_str);
  534. if (0 == strcmp(h_ota->md5sum, md5_str)) {
  535. *((uint32_t *)buf) = 1;
  536. } else {
  537. *((uint32_t *)buf) = 0;
  538. // report MD5 inconsistent
  539. IOT_OTA_ReportUpgradeResult(h_ota, h_ota->version, IOT_OTAR_MD5_NOT_MATCH);
  540. }
  541. return 0;
  542. }
  543. default:
  544. Log_e("invalid cmd type");
  545. h_ota->err = IOT_OTA_ERR_INVALID_PARAM;
  546. return QCLOUD_ERR_FAILURE;
  547. }
  548. return 0;
  549. }
  550. /* Get last error code */
  551. int IOT_OTA_GetLastError(void *handle)
  552. {
  553. OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
  554. if (NULL == handle) {
  555. Log_e("handle is NULL");
  556. return IOT_OTA_ERR_INVALID_PARAM;
  557. }
  558. return h_ota->err;
  559. }
  560. #ifdef __cplusplus
  561. }
  562. #endif