# OTA API

本系统提供底层刷写库 libupdate.so，并实现了一套跨平台的 API，用于烧写 OTA 升级包。

源码路径：`hbre/otaupdate/src/ota_apis/hobot_ota_hl.c`

头文件: `hobot_ota_hl.h`

针对 OTA HighLevel API开发了ota_tool 工具，使用该工具可以帮助客户在设计 OTA Service 时更便捷地参考和实现相关功能。

源码路径：`hbre/otaupdate/src/ota_tool`

头文件: `hobot_ota_hl.h`

链接库: `libupdate.so`


## 动态库接口返回的错误类型

动态库错误值定义如下：

```C
enum ota_err_e {
    OTA_SUCCESS = 0,
    OTAERR_IO,
    OTAERR_PLAT_UNSUPPORT,
    OTAERR_REPEAT,
    OTAERR_MUTEX_INIT_LOCK_ERR,
    OTAERR_NOTINIT,
    OTAERR_NULLPOINTER,
    OTAERR_SHORTBUF,
    OTAERR_THREAD_CREATE,
    OTAERR_RANGE,
    OTAERR_STAGE,
    OTAERR_IMAGE_WRITE,
    OTAERR_BOOT_FAILED,
    OTAERR_VEEPROM,
    OTAERR_FILE_TYPE,
    OTAERR_UNZIP,
    OTAERR_NO_EXISTS,
    OTAERR_MALLOC,
    OTAERR_VERIFY,
    OTAERR_IMG_SIZE,
    OTAERR_UPDATE_STATUS,
}
```

## 接口列表

| 接口原型                                                                      | 描述                        |
|------------------------------------------------------------------------------ |----------------------------|
| int32_t otaInitLib(void);                                                     | 动态库初始化                |
| int32_t otaDeinitLib(void);                                                   | 动态库反初始化              |
| int32_t otaGetLibVersion(char \*version, int32_t len);                        | 获取动态库版本              |
| int32_t otaRequestStart(const char \*image_name, enum ota_update_owner owner);| 启动升级线程                |
| int32_t otaGetResult(void);                                                   | 获取升级状态和结果          |
| int32_t otaGetProgress(void);                                                 | 获取升级进度                |
| int32_t otaGetUpdatingImageName(char \*image_name , int32_t len);             | 获取正在升级的包            |
| int32_t otaGetSysVersion(char \*version, int32_t len);                        | 获取当前系统版本            |
| int32_t otaGetPartition(uint8_t \*partition);                                 | 获取当前启动的 AB 分区      |
| int32_t otaSetPartition(uint8_t partition);                                   | 设置下次启动的 AB 分区      |
| int32_t otaGetOwnerFlag(enum ota_update_owner \*owner);                       | 获取 OTA owner（重启后）    |
| int32_t otaMarkOTASuccessful(void);                                           | 标记 OTA 升级成功（重启后）  |
| int32_t otaCheckUpdate(void);                                                 | 检查是否升级成功（重启后）   |
| int32_t otaPartitionSync(void);                                               | AB 分区、bak 分区同步       |
| void otaClearFlags(void);                                                     | 结束升级，清除 ota 标志     |

### otaInitLib

【函数声明】

int32_t otaInitLib(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_REPEAT: 重复初始化

【功能描述】

板端刷写接口动态库初始化，主要进行全局结构体g_upgrade_info的初始化。

#### <span id="otaInitLib-code"/>【示例代码】
```C
#include <stdio.h>
#include <hobot_ota_hl.h>
int main(void) {
    int32_t ret;
    ret = otaInitLib();
    if (ret != 0) {
        printf("otaInitLib return: %d\n", ret);
        return ret;
    }
    ret = otaDeinitLib();
    if (ret != 0) {
        printf("otaDeinitLib return: %d\n", ret);
        return ret;
    }
    return 0;
}
```

### otaDeinitLib

【函数声明】

int32_t otaDeinitLib(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NOTINIT: 当前未初始化，不能调用反初始化

【功能描述】

反初始化

#### 【示例代码】
参考 [otaInitLib](./2-ota-api.html#span-id-otainitlib-code)

### otaGetLibVersion

【函数声明】

int32_t otaGetLibVersion(char *version, int32_t len);

【参数描述】

- [OUT] version: 用于存储 version 信息。version以三段式字符串形式返回（如：1.0.0）
- [IN] len: 传入的 buffer 长度

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NULLPOINTER: version 空指针
- -OTAERR_SHORTBUF: 传入的 buffer 过小
- -OTAERR_PLAT_UNSUPPORT: 不支持获取版本号

【功能描述】

获取本动态库版本

#### 【示例代码】
```C
#include <stdio.h>
#include <hobot_ota_hl.h>
int main(void) {
    int32_t ret;
    char version[128];
    if (ret = otaGetLibVersion(version, sizeof(version))) {
        return ret;
    }
    printf("version: %s\n", version);
}
```

### <span id="otaRequestStart"/> otaRequestStart

【函数声明】

int32_t otaRequestStart(const char *image_name, enum ota_update_owner owner);

【参数描述】

- [OUT] N/A
- [IN] image_name: 升级包绝对路径。支持多种不同类型的包同时传入，用分号隔开。
- [IN] owner: 发起本次升级的进程， owner 由 enum ota_update_owner 定义

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NULLPOINTER: image_name 空指针
- -OTAERR_RANGE: owner设置错误，超出当前定义范围
- -OTAERR_NOTINIT: 未初始化本动态库
- -OTAERR_REPEAT: 当前有其他进程正在升级
- -OTAERR_IO: IO失败
- -OTAERR_THREAD_CREATE: 线程创建失败

【功能描述】

启动升级线程，对传入的image_name进行升级，并设置当前升级所有者

#### 【示例代码】
```C
#include <stdio.h>
#include <hobot_ota_hl.h>
int main(void) {
    int32_t ret;
    int32_t result;
    int32_t progress;
    char imgname[256];
    ret = otaInitLib();
    if (ret != 0) {
        printf("otaInitLib return: %d\n", ret);
        return ret;
    }
    if (ret = otaRequestStart("/userdata/all_in_one.zip", OTA_TOOL)) {
        printf("otaRequestStart return: %d\n", ret);
        return ret;
    }
    do {
        result = otaGetResult();
        if (ret = otaGetUpdatingImageName(imgname, sizeof(imgname))) {
            printf("otaGetUpdatingImageName return: %d\n", imgname);
        }
        progress = otaGetProgress();
        printf("current image: %s, progress: %d\n", imgname, progress);
        sleep(1);
    } while(result != 0 && result != 3);

    ret = otaGetPartition(&cur_part);
    if (ret != 0) {
        printf("otaGetPartition returned with %d\n", ret);
    }
    ret = otaSetPartition(1 - cur_part);
    if (ret != 0) {
        printf("otaSetPartition returned with %d\n", ret);
    }
    /* Then reboot system */
    return 0;
}
```

### otaGetResult

【函数声明】

int32_t otaGetResult(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- OTA_UPGRADE_NOT_START: 升级未开始
- OTA_UPGRADE_IN_PROGRESS: 升级中
- OTA_UPGRADE_SUCCESS: 升级结束，成功
- OTA_UPGRADE_FAILED: 升级结束，失败
- -OTAERR_NOTINIT: 未初始化本动态库

【功能描述】

获取升级结果

#### 【示例代码】
参考 [otaRequestStart](./2-ota-api.html#span-id-otarequeststart-otarequeststart)

### otaGetProgress

【函数声明】

int32_t otaGetProgress(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- 0 ~ 100: 当前升级进度(%)
- -OTAERR_NOTINIT: 未初始化本动态库

【功能描述】

获取当前升级进度

#### 【示例代码】
参考 [otaRequestStart](./2-ota-api.html#span-id-otarequeststart-otarequeststart)

### otaGetUpdatingImageName

【函数声明】

int32_t otaGetUpdatingImageName(char *image_name , int32_t len);

【参数描述】

- [OUT] image_name: 用于存放结果的 buffer。
image_name 可能出现的内容：
 "idle_state"–升级未开始
 "all_img_finish"–升级完成
 ""–未开始烧写镜像就失败
 其他以".img"结尾的包名

- [IN] len: buffer 长度

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NULLPOINTER: image_name 空指针
- -OTAERR_NOTINIT: 本动态库未初始化
- -OTAERR_SHORTBUF: buffer长度太短

【功能描述】

获取当前正在升级的镜像

#### 【示例代码】
参考 [otaRequestStart](./2-ota-api.html#span-id-otarequeststart-otarequeststart)

### otaGetSysVersion

【函数声明】

int32_t otaGetSysVersion(char *version, int32_t len);

【参数描述】

- [OUT] version: 用于存储 version 信息。version 中保存系统软件版本，以日期开头(yyyymmdd)
- [IN] len: 传入的 buffer 长度

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NULLPOINTER: version 空指针
- -OTAERR_SHORTBUF: 传入的 buffer 过小
- -OTAERR_IO: io 错误，请重试

【功能描述】

获取当前系统软件版本

#### 【示例代码】
```C
#include <stdio.h>
#include <hobot_ota_hl.h>
int main(void) {
    int32_t ret;
    char version[128];
    if (ret = otaGetSysVersion(version, sizeof(version))) {
        printf("otaGetSysVersion return: %d\n", ret);
        return -1;
    }
    printf("current system version: %s\n", version);
    return 0;
}
```

### otaGetPartition

【函数声明】

int32_t otaGetPartition(uint8_t *partition);

【参数描述】

- [OUT] partition: 用于接收当前分区的变量地址。
*partition=0：当前为 A 分区，*partition=1：当前为 B 分区
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NULLPOINTER: partition 为空指针
- -OTAERR_IO: io 错误，请重试

【功能描述】

获取当前启动 AB 分区

#### 【示例代码】
参考 [otaRequestStart](./2-ota-api.html#span-id-otarequeststart-otarequeststart)

### otaSetPartition

【函数声明】

int32_t otaSetPartition(uint8_t partition);

【参数描述】

- [OUT] N/A
- [IN] partition: 下次启动分区。0：A 分区，1：B 分区

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NOTINIT: 本动态库未初始化
- -OTAERR_RANGE: partition 范围错误，partition 范围为0和1
- -OTAERR_IO: io 错误，请重试
- -OTAERR_STAGE: 当前升级阶段不支持。升级过程中或升级失败不支持

【功能描述】

设置下次启动的 AB 分区

#### 【示例代码】
参考 [otaRequestStart](./2-ota-api.html#span-id-otarequeststart-otarequeststart)

### <span id="otaGetOwnerFlag"/> otaGetOwnerFlag

【函数声明】

int32_t otaGetOwnerFlag(enum ota_update_owner *owner);

【参数描述】

- [OUT] owner: 用于接收当前升级 owner 的变量。请参考 enum ota_update_owner
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NOTINIT: 未初始化
- -OTAERR_NULLPOINTER: partition 为空指针
- -OTAERR_IO: io 错误，请重试

【功能描述】

获取当前升级 owner

#### 【示例代码】
```C
static int check_and_mark(void) {
    enum ota_update_owner owner;
    int32_t ret;
    ret = otaGetOwnerFlag(&owner);
    if (ret != 0) {
            printf("otaGetOwnerFlag returned with %d\n", ret);
            return -1;
    }
    if (owner != OTA_TOOL) {
            printf("The OTA update is not launched by ota_tool, owner: %d\n", owner);
            return -1;
    }
    ret = otaCheckUpdate();
    if (ret == -OTAERR_IMAGE_WRITE) {
            printf("ota_tool: OTA image write failed, is there a reboot during update?\n");
            goto clearFlags;
    }
    if (ret == -OTAERR_BOOT_FAILED) {
            printf("ota_tool: The new package boot failed. Please check the packages\n");
            goto clearFlags;
    }
    if (ret != 0) {
            printf("otaCheckUpdate returned with %d\n", ret);
            goto clearFlags;
    }
    ret = otaMarkOTASuccessful();
    if (ret != 0) {
            printf("otaMarkOTASuccessful returned with %d\n", ret);
            goto clearFlags;
    }
    ret = otaPartitionSync();
    if (ret != 0) {
            printf("otaPartitionSync returned with %d\n", ret);
            goto clearFlags;
    }
clearFlags:
    otaClearFlags();
    return ret;
}
```

### otaMarkOTASuccessful

【函数声明】

int32_t otaMarkOTASuccessful(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_NOTINIT: 未初始化
- -OTAERR_IO: io 错误，请重试

【功能描述】

标记本次升级成功

#### 【示例代码】

参考 [otaGetOwnerFlag](./2-ota-api.html#span-id-otagetownerflag-otagetownerflag)

### otaCheckUpdate

【函数声明】

int32_t otaCheckUpdate(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- OTA_SUCCESS: 成功
- -OTAERR_IO: io 错误，请重试
- -OTAERR_STAGE: 未进行升级
- -OTAERR_IMAGE_WRITE: 镜像写入失败
- -OTAERR_BOOT_FAILED: 新镜像启动失败或未切换分区

【功能描述】

检查本次升级是否成功

#### 【示例代码】
参考 [otaGetOwnerFlag](./2-ota-api.html#span-id-otagetownerflag-otagetownerflag)

### otaClearFlags

【函数声明】

void otaClearFlags(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- N/A

【功能描述】

清除 OTA flags

#### 【示例代码】
参考 [otaGetOwnerFlag](./2-ota-api.html#span-id-otagetownerflag-otagetownerflag)

### otaPartitionSync

【函数声明】

int32_t otaPartitionSync(void);

【参数描述】

- [OUT] N/A
- [IN] N/A

【返回值】

- -OTAERR_NOTINIT: 未初始化
- -OTAERR_IO: io 错误
- -OTAERR_REPEAT: 与其他升级进程冲突
- OTA_SUCCESS: 成功

【功能描述】

AB分区、bak分区同步

#### 【示例代码】
参考 [otaGetOwnerFlag](./2-ota-api.html#span-id-otagetownerflag-otagetownerflag)

