156 lines
3.9 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include "btstack/bluetooth.h"
#include "system/includes.h"
#include "bt_common.h"
#include "api/sig_mesh_api.h"
#include "model_api.h"
#include "mesh_dfu_app_cmd_protocol.h"
#define LOG_TAG "[Mesh-DFU_Dist]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if (CONFIG_BT_MESH_DFU_DIST)
static struct bt_mesh_blob_io_flash *blob_flash_stream;
static int hex2char(uint8_t x, char *c)
{
if (x <= 9) {
*c = x + (char)'0';
} else if (x <= 15) {
*c = x - 10 + (char)'a';
} else {
return -EINVAL;
}
return 0;
}
static size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
{
if (hexlen < (buflen * 2U + 1U)) {
return 0;
}
for (size_t i = 0; i < buflen; i++) {
if (hex2char(buf[i] >> 4, &hex[2U * i]) < 0) {
return 0;
}
if (hex2char(buf[i] & 0xf, &hex[2U * i + 1U]) < 0) {
return 0;
}
}
hex[2U * buflen] = '\0';
return 2U * buflen;
}
static void slot_info_print(const struct bt_mesh_dfu_slot *slot, const u8_t *idx)
{
char fwid[2 * CONFIG_BT_MESH_DFU_FWID_MAXLEN + 1];
char metadata[2 * CONFIG_BT_MESH_DFU_METADATA_MAXLEN + 1];
size_t len;
len = bin2hex(slot->fwid, slot->fwid_len, fwid, sizeof(fwid));
fwid[len] = '\0';
len = bin2hex(slot->metadata, slot->metadata_len, metadata,
sizeof(metadata));
metadata[len] = '\0';
if (idx != NULL) {
log_info("Slot %u:", *idx);
} else {
log_info("Slot:");
}
log_info("\tSize: %u bytes", slot->size);
log_info("\tFWID: %s", fwid);
log_info("\tMetadata: %s", metadata);
}
static int dfd_srv_recv(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io)
{
log_info("Uploading new firmware image to the distributor.");
slot_info_print(slot, NULL);
*io = &blob_flash_stream->io;
return 0;
}
static void dfd_srv_del(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot)
{
log_info("Deleting the firmware image from the distributor.");
slot_info_print(slot, NULL);
}
static int dfd_srv_send(struct bt_mesh_dfd_srv *srv,
const struct bt_mesh_dfu_slot *slot,
const struct bt_mesh_blob_io **io)
{
log_info("Starting the firmware distribution.");
slot_info_print(slot, NULL);
*io = &blob_flash_stream->io;
return 0;
}
static const char *dfd_phase_to_str(enum bt_mesh_dfd_phase phase)
{
switch (phase) {
case BT_MESH_DFD_PHASE_IDLE:
return "Idle";
case BT_MESH_DFD_PHASE_TRANSFER_ACTIVE:
return "Transfer Active";
case BT_MESH_DFD_PHASE_TRANSFER_SUCCESS:
return "Transfer Success";
case BT_MESH_DFD_PHASE_APPLYING_UPDATE:
return "Applying Update";
case BT_MESH_DFD_PHASE_COMPLETED:
return "Completed";
case BT_MESH_DFD_PHASE_FAILED:
return "Failed";
case BT_MESH_DFD_PHASE_CANCELING_UPDATE:
return "Canceling Update";
case BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED:
return "Transfer Suspended";
default:
return "Unknown Phase";
}
}
static void dfd_srv_phase(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_phase phase)
{
log_info("Distribution phase changed to %s", dfd_phase_to_str(phase));
set_dfu_distributor_state(phase, 0x00);
}
static struct bt_mesh_dfd_srv_cb dfd_srv_cb = {
.recv = dfd_srv_recv,
.del = dfd_srv_del,
.send = dfd_srv_send,
.phase = dfd_srv_phase,
};
struct bt_mesh_dfd_srv dfd_srv = BT_MESH_DFD_SRV_INIT(&dfd_srv_cb);
void dfu_distributor_init(struct bt_mesh_blob_io_flash *flash_stream)
{
blob_flash_stream = flash_stream;
}
#endif