This commit is contained in:
Ben V. Brown
2022-10-21 19:49:20 +11:00
parent 0c18c45490
commit 736bedc51a
11 changed files with 395 additions and 2104 deletions

View File

@@ -1,363 +0,0 @@
#include "ble_lib_api.h"
#include "bluetooth.h"
#include "conn.h"
#include "hci_core.h"
#include "hci_driver.h"
#include "byteorder.h"
#include "log.h"
#include "errno.h"
struct blhast_le_adv_data {
u8_t ad[31];
size_t ad_len;
};
static struct bt_le_scan_param blhast_le_scan_param;
static struct bt_le_adv_param blhast_le_adv_param;
static struct blhast_le_adv_data blhast_le_ad;
static struct blhast_le_adv_data blhast_le_sd;
static bt_le_scan_cb_t *blhast_le_scan_cb;
static void blhast_ble_scan_assist_cb(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb);
static void blhast_ble_adv_assist_cb(const struct bt_le_adv_param *param, const struct bt_data *ad,
size_t ad_len, const struct bt_data *sd, size_t sd_len);
static struct blhast_cb assist_cb = {
.le_scan_cb = blhast_ble_scan_assist_cb,
.le_adv_cb = blhast_ble_adv_assist_cb,
};
extern struct bt_dev bt_dev;
static void blhast_ble_scan_assist_cb(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb)
{
memcpy(&blhast_le_scan_param, param, sizeof(struct bt_le_scan_param));
blhast_le_scan_cb = cb;
}
static void blhast_ble_get_ad(const struct bt_data *ad, size_t ad_len, uint8_t *output)
{
int i;
uint8_t data_len = 0;
for (i = 0; i < ad_len; i++) {
*(output + data_len) = ad[i].type;
data_len++;
*(output + data_len) = ad[i].data_len;
data_len++;
memcpy(output + data_len, ad[i].data, ad[i].data_len);
data_len += ad[i].data_len;
}
}
static void blhast_ble_construct_ad(struct blhast_le_adv_data *adv_data, struct bt_data *output)
{
int i;
size_t ad_len = adv_data->ad_len;
u8_t *p_ad = adv_data->ad;
for (i = 0; i < ad_len; i++) {
memcpy(&output[i], p_ad, 2); //type, data_len
p_ad += 2;
output[i].data = (const u8_t *)p_ad;
p_ad += output[i].data_len;
}
}
static void blhast_ble_adv_assist_cb(const struct bt_le_adv_param *param, const struct bt_data *ad,
size_t ad_len, const struct bt_data *sd, size_t sd_len)
{
memcpy(&blhast_le_adv_param, param, sizeof(struct bt_le_adv_param));
if (ad) {
blhast_le_ad.ad_len = ad_len;
memset(blhast_le_ad.ad, 0, sizeof(blhast_le_ad.ad));
blhast_ble_get_ad(ad, ad_len, blhast_le_ad.ad);
}
if (sd) {
blhast_le_sd.ad_len = sd_len;
memset(blhast_le_sd.ad, 0, sizeof(blhast_le_sd.ad));
blhast_ble_get_ad(sd, sd_len, blhast_le_sd.ad);
}
}
static int blhast_common_reset(void)
{
struct net_buf *rsp;
int err;
if (!(bt_dev.drv->quirks & BT_QUIRK_NO_RESET)) {
/* Send HCI_RESET */
err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, &rsp);
if (err) {
return err;
}
bt_hci_reset_complete(rsp);
net_buf_unref(rsp);
}
#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
err = bt_set_flow_control();
if (err) {
return err;
}
#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
return 0;
}
static int blhast_ble_reset(void)
{
struct bt_hci_cp_write_le_host_supp *cp_le;
struct net_buf *buf, *rsp;
int err;
if (!BT_FEAT_LE(bt_dev.features)) {
BT_ERR("Non-LE capable controller detected!");
return -ENODEV;
}
if (BT_FEAT_BREDR(bt_dev.features)) {
buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP,
sizeof(*cp_le));
if (!buf) {
return -ENOBUFS;
}
cp_le = net_buf_add(buf, sizeof(*cp_le));
/* Explicitly enable LE for dual-mode controllers */
cp_le->le = 0x01;
cp_le->simul = 0x00;
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, buf,
NULL);
if (err) {
return err;
}
}
if (IS_ENABLED(CONFIG_BT_CONN) &&
IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
BT_FEAT_LE_DLE(bt_dev.le.features)) {
struct bt_hci_cp_le_write_default_data_len *cp;
struct bt_hci_rp_le_read_max_data_len *rp;
u16_t tx_octets, tx_time;
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL,
&rsp);
if (err) {
return err;
}
rp = (void *)rsp->data;
tx_octets = sys_le16_to_cpu(rp->max_tx_octets);
tx_time = sys_le16_to_cpu(rp->max_tx_time);
net_buf_unref(rsp);
buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->max_tx_octets = sys_cpu_to_le16(tx_octets);
cp->max_tx_time = sys_cpu_to_le16(tx_time);
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
buf, NULL);
if (err) {
return err;
}
}
return bt_le_set_event_mask();
}
#if defined(CONFIG_BT_BREDR)
static int blhast_br_reset(void)
{
struct net_buf *buf;
struct bt_hci_cp_write_ssp_mode *ssp_cp;
struct bt_hci_cp_write_inquiry_mode *inq_cp;
struct bt_hci_write_local_name *name_cp;
int err;
/* Set SSP mode */
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SSP_MODE, sizeof(*ssp_cp));
if (!buf) {
return -ENOBUFS;
}
ssp_cp = net_buf_add(buf, sizeof(*ssp_cp));
ssp_cp->mode = 0x01;
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SSP_MODE, buf, NULL);
if (err) {
return err;
}
/* Enable Inquiry results with RSSI or extended Inquiry */
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_INQUIRY_MODE, sizeof(*inq_cp));
if (!buf) {
return -ENOBUFS;
}
inq_cp = net_buf_add(buf, sizeof(*inq_cp));
inq_cp->mode = 0x02;
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_INQUIRY_MODE, buf, NULL);
if (err) {
return err;
}
/* Set local name */
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_LOCAL_NAME, sizeof(*name_cp));
if (!buf) {
return -ENOBUFS;
}
name_cp = net_buf_add(buf, sizeof(*name_cp));
strncpy((char *)name_cp->local_name, CONFIG_BT_DEVICE_NAME,
sizeof(name_cp->local_name));
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_LOCAL_NAME, buf, NULL);
if (err) {
return err;
}
/* Set page timeout*/
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_PAGE_TIMEOUT, sizeof(u16_t));
if (!buf) {
return -ENOBUFS;
}
net_buf_add_le16(buf, CONFIG_BT_PAGE_TIMEOUT);
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_PAGE_TIMEOUT, buf, NULL);
if (err) {
return err;
}
/* Enable BR/EDR SC if supported */
if (BT_FEAT_SC(bt_dev.features)) {
struct bt_hci_cp_write_sc_host_supp *sc_cp;
buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SC_HOST_SUPP,
sizeof(*sc_cp));
if (!buf) {
return -ENOBUFS;
}
sc_cp = net_buf_add(buf, sizeof(*sc_cp));
sc_cp->sc_support = 0x01;
err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SC_HOST_SUPP, buf,
NULL);
if (err) {
return err;
}
}
return 0;
}
#endif
static int blhast_host_hci_reset(void)
{
int err;
ATOMIC_DEFINE(old_flags, BT_DEV_NUM_FLAGS);
memcpy(old_flags, bt_dev.flags, sizeof(old_flags));
err = blhast_common_reset();
if (err) {
return err;
}
err = blhast_ble_reset();
if (err) {
return err;
}
#if defined(CONFIG_BT_BREDR)
if (BT_FEAT_BREDR(bt_dev.features)) {
err = blhast_br_reset();
if (err) {
return err;
}
}
#endif
err = bt_set_event_mask();
if (err) {
return err;
}
memcpy(bt_dev.flags, old_flags, sizeof(old_flags));
return 0;
}
static void blhast_host_state_restore(void)
{
struct bt_data *ad = NULL;
struct bt_data *sd = NULL;
k_sem_give(&bt_dev.ncmd_sem);
net_buf_unref(bt_dev.sent_cmd);
bt_dev.sent_cmd = NULL;
blhast_host_hci_reset();
#if defined(CONFIG_BT_CONN)
bt_notify_disconnected();
#endif
atomic_set_bit(bt_dev.flags, BT_DEV_ASSIST_RUN);
#if defined(CONFIG_BT_OBSERVER)
if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
BT_WARN("Restore BLE scan\r\n");
atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING);
bt_le_scan_start((const struct bt_le_scan_param *)&blhast_le_scan_param, blhast_le_scan_cb);
}
#endif
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
BT_WARN("Restore BLE advertising\r\n");
if (blhast_le_ad.ad_len > 0) {
ad = k_malloc(sizeof(struct bt_data) * blhast_le_ad.ad_len);
blhast_ble_construct_ad(&blhast_le_ad, ad);
}
if (blhast_le_sd.ad_len > 0) {
sd = k_malloc(sizeof(struct bt_data) * blhast_le_sd.ad_len);
blhast_ble_construct_ad(&blhast_le_sd, sd);
}
bt_le_adv_start((const struct bt_le_adv_param *)&blhast_le_adv_param, ad,
blhast_le_ad.ad_len, sd, blhast_le_sd.ad_len);
if (ad)
k_free(ad);
if (sd)
k_free(sd);
}
atomic_clear_bit(bt_dev.flags, BT_DEV_ASSIST_RUN);
}
void blhast_bt_reset(void)
{
ble_controller_reset();
blhast_host_state_restore();
}
void blhast_init(void)
{
memset(&blhast_le_ad, 0, sizeof(struct blhast_le_adv_data));
memset(&blhast_le_sd, 0, sizeof(struct blhast_le_adv_data));
bt_register_host_assist_cb(&assist_cb);
}

View File

@@ -35,7 +35,7 @@
#include "att_internal.h"
#include "gatt_internal.h"
#if defined(BFLB_BLE)
#include "config.h"
#include "ble_config.h"
extern struct k_sem g_poll_sem;
#endif

View File

@@ -30,7 +30,7 @@
#include <gatt.h>
#include <hci_driver.h>
#if defined(BFLB_BLE)
#include "config.h"
#include "ble_config.h"
#include <util.h>
#endif

View File

@@ -26,7 +26,7 @@
#include "conn_internal.h"
#include "l2cap_internal.h"
#include "config.h"
#include "ble_config.h"
#define LE_CHAN_RTX(_w) CONTAINER_OF(_w, struct bt_l2cap_le_chan, chan.rtx_work)
#define CHAN_RX(_w) CONTAINER_OF(_w, struct bt_l2cap_le_chan, rx_work)

View File

@@ -7,6 +7,7 @@
*/
#include <zephyr.h>
#include <ble_config.h>
#include <string.h>
#include <errno.h>
#include <atomic.h>

View File

@@ -14,7 +14,6 @@ NOTES
#include <stdlib.h>
#include <FreeRTOS.h>
#include <task.h>
#include <blog.h>
#include "bluetooth.h"
#include "conn.h"

View File

@@ -1,625 +0,0 @@
#include <stdbool.h>
#include <string.h>
#include <net/buf.h>
#include "oad_service.h"
#include "oad.h"
#include "oad_main.h"
#ifdef CONFIG_BT_SETTINGS
#include "settings.h"
#include "ef_def.h"
#endif
#include "conn_internal.h"
#if !defined(CONFIG_BL_MCU_SDK)
#include "hal_boot2.h"
#include "bl_flash.h"
#include "bl_sys.h"
#include "hosal_ota.h"
#include "bl702_common.h"
#include "hal_sys.h"
#else
#include "partition.h"
#include "hal_flash.h"
#include "errno.h"
#include "bl702_glb.h"
#include "mbedtls/sha256.h"
#endif
#include "log.h"
#include "bl702.h"
#include "softcrc.h"
#if defined(CONFIG_BL_MCU_SDK)
#define BL_SDK_VER "1.00"
#define BOOT2_PARTITION_ADDR (0x4202DC00)
#endif //CONFIG_BL_MCU_SDK
#define OTA_WRITE_FLASH_SIZE (256 * 16)
#define WBUF_SIZE(CON) (OTA_WRITE_FLASH_SIZE + bt_gatt_get_mtu(CON))
#define UPGRD_TIMEOUT K_SECONDS(2)
static app_check_oad_cb app_check_cb = NULL;
struct oad_env_tag oad_env;
struct wflash_data_t {
u8_t *wdata_buf;
u16_t index;
} __packed;
static struct wflash_data_t wData;
#if defined(CONFIG_BL_MCU_SDK)
static int hal_boot2_partition_addr_inactive(const char *name, uint32_t *addr, uint32_t *size);
static int hal_boot2_get_active_entries_byname(u8_t *name, pt_table_entry_config *ptEntry_hal);
static int hal_boot2_update_ptable(pt_table_entry_config *ptEntry_hal);
static int fw_check_hash256(void);
#endif
static bool check_data_valid(struct oad_file_info *file_info)
{
if (file_info->manu_code != oad_env.file_info.manu_code || file_info->file_ver != oad_env.upgrd_file_ver)
return false;
return true;
}
static void oad_notify_image_info(struct bt_conn *conn)
{
u8_t *buf = (u8_t *)k_malloc(sizeof(u8_t) * 256);
u8_t index = 0;
char *build_date = __DATE__;
char *build_time = __TIME__;
char *build_ver = BL_SDK_VER;
if (buf) {
memset(buf, 0, 256);
} else {
BT_WARN("Buffer allocation failed\r\n");
return;
}
buf[index++] = OAD_CMD_IMAG_INFO;
if (strlen(build_date) + index <= 256) {
buf[index] = strlen(build_date);
memcpy(&buf[++index], build_date, strlen(build_date));
index += strlen(build_date);
} else {
BT_WARN("No enough space\r\n");
}
if (strlen(build_time) + index <= 256) {
buf[index] = strlen(build_time);
memcpy(&buf[++index], build_time, strlen(build_time));
index += strlen(build_time);
} else {
BT_WARN("No enough space\r\n");
}
if (strlen(build_ver) + index <= 256) {
buf[index] = strlen(build_ver);
memcpy(&buf[++index], build_ver, strlen(build_ver));
index += strlen(build_ver);
} else {
BT_WARN("No enough space\r\n");
}
BT_WARN("Info:%s,%s,%s\r\n", build_date, build_time, build_ver);
BT_WARN("Send:%s\r\n", bt_hex(buf, index));
bt_oad_notify(conn, buf, index);
k_free(buf);
}
static void oad_notify_block_req(struct bt_conn *conn)
{
struct net_buf_simple *buf = NET_BUF_SIMPLE(sizeof(struct oad_block_req_t) + OAD_OPCODE_SIZE);
struct oad_block_req_t *block_req;
net_buf_simple_init(buf, 0);
*(buf->data) = OAD_CMD_IMAG_BLOCK_REQ;
block_req = (struct oad_block_req_t *)(buf->data + 1);
buf->len = sizeof(struct oad_block_req_t) + OAD_OPCODE_SIZE;
block_req->file_info.file_ver = oad_env.upgrd_file_ver;
block_req->file_info.manu_code = oad_env.file_info.manu_code;
block_req->file_offset = oad_env.upgrd_offset;
bt_oad_notify(conn, buf->data, buf->len);
}
static void oad_notify_upgrd_end(struct bt_conn *conn, u8_t status)
{
struct net_buf_simple *buf = NET_BUF_SIMPLE(sizeof(struct oad_upgrd_end_t) + OAD_OPCODE_SIZE);
struct oad_upgrd_end_t *upgrd_end;
if (status == OAD_SUCC) {
BT_WARN("Submit upgrade work\r\n");
#if !defined(CONFIG_BL_MCU_SDK)
if (!hosal_ota_finish(1, 0))
#else
if (!fw_check_hash256())
#endif
k_delayed_work_submit(&oad_env.upgrd_work, UPGRD_TIMEOUT);
else {
BT_WARN("Hash256 check failed");
status = OAD_CHECK_HASH256_FAIL;
}
}
net_buf_simple_init(buf, 0);
*(buf->data) = OAD_CMD_IMAG_UPGRD_END;
upgrd_end = (struct oad_upgrd_end_t *)(buf->data + 1);
buf->len = sizeof(struct oad_upgrd_end_t) + OAD_OPCODE_SIZE;
upgrd_end->file_info.file_ver = oad_env.upgrd_file_ver;
upgrd_end->file_info.manu_code = oad_env.file_info.manu_code;
upgrd_end->status = status;
bt_oad_notify(conn, buf->data, buf->len);
}
static void oad_notity_image_identity(struct bt_conn *conn)
{
struct net_buf_simple *buf = NET_BUF_SIMPLE(sizeof(struct oad_image_identity_t));
struct oad_image_identity_t *identity;
net_buf_simple_init(buf, 0);
*(buf->data) = OAD_CMD_IMAG_IDENTITY;
identity = (void *)(buf->data + 1);
buf->len = sizeof(struct oad_image_identity_t) + OAD_OPCODE_SIZE;
identity->file_info.file_ver = oad_env.file_info.file_ver;
identity->file_info.manu_code = oad_env.file_info.manu_code;
identity->file_size = oad_env.cur_file_size;
identity->crc32 = 0;
bt_oad_notify(conn, buf->data, buf->len);
}
void ota_finish(struct k_work *work)
{
BT_WARN("oad_upgrade\r\n");
oad_env.file_info.file_ver = oad_env.upgrd_file_ver;
#if defined(CONFIG_BT_SETTINGS)
struct oad_ef_info ef_info;
memset(&ef_info, 0, sizeof(struct oad_ef_info));
bt_settings_set_bin(NV_IMG_info, (uint8_t *)&ef_info, sizeof(struct oad_ef_info));
#endif
#if defined(CONFIG_BL_MCU_SDK)
GLB_SW_System_Reset();
#else
hal_reboot();
#endif
}
static u8_t oad_write_flash(uint32_t filesize, uint32_t offset, u8_t *data, u16_t len)
{
#if defined(CONFIG_BL_MCU_SDK)
uint32_t size = 0;
uint32_t wflash_address = 0;
if (!oad_env.new_img_addr) {
if (hal_boot2_partition_addr_inactive("FW", (uint32_t *)&oad_env.new_img_addr, &size)) {
BT_WARN("New img address is null\r\n");
return OAD_ABORT;
}
BT_WARN("Upgrade file size is %d\r\n", oad_env.upgrd_file_size);
if (oad_env.upgrd_file_size <= size) {
BT_WARN("flash erase\r\n");
flash_erase(oad_env.new_img_addr, oad_env.upgrd_file_size);
} else {
return -1;
}
}
BT_WARN("upgrd_offset is 0x%x len (%d)\r\n", oad_env.upgrd_offset, len);
if (oad_env.w_img_end_addr <= oad_env.new_img_addr && !oad_env.w_img_end_addr) {
wflash_address = oad_env.new_img_addr;
} else if (oad_env.w_img_end_addr) {
wflash_address = oad_env.w_img_end_addr;
} else {
BT_WARN("Write flash address invalid\r\n");
}
BT_WARN("Start address : 0x%x\r\n", wflash_address);
flash_write(wflash_address, data, len);
oad_env.w_img_end_addr = wflash_address + len;
BT_WARN("End address : 0x%x\r\n", wflash_address + len);
#else
hosal_ota_update(filesize, offset, data, len);
#endif
return 0;
}
static u8_t oad_image_data_handler(struct bt_conn *conn, const u8_t *data, u16_t len)
{
u16_t left_size = 0;
u16_t oDataLen = 0;
static u32_t write_count = 0;
if (!wData.wdata_buf) {
wData.wdata_buf = (u8_t *)k_malloc(WBUF_SIZE(conn));
if (!wData.wdata_buf) {
BT_WARN("Buf is NULL\r\n");
return OAD_ABORT;
};
memset(wData.wdata_buf, 0, WBUF_SIZE(conn));
wData.index = 0;
}
if (wData.wdata_buf) {
left_size = /*WBUF_SIZE(conn)*/ OTA_WRITE_FLASH_SIZE - wData.index;
BT_WARN("left_size (0x%x) wData.index (0x%x) len (%d)\r\n", left_size, wData.index, len);
if (left_size >= len) {
memcpy((wData.wdata_buf + wData.index), data, len);
wData.index += len;
} else {
oDataLen = len - left_size;
memcpy((wData.wdata_buf + wData.index), data, left_size);
wData.index += left_size;
if (wData.index == OTA_WRITE_FLASH_SIZE) {
if (oad_write_flash(oad_env.upgrd_file_size, oad_env.hosal_offset, wData.wdata_buf, OTA_WRITE_FLASH_SIZE)) {
BT_ERR("Failed to write flash\r\n");
return OAD_ABORT;
}
} else {
BT_ERR("Unexpect result\r\n");
return OAD_ABORT;
}
write_count += 1;
oad_env.hosal_offset = write_count * OTA_WRITE_FLASH_SIZE;
#if defined(CONFIG_BT_SETTINGS)
struct oad_ef_info ef_info;
memcpy(&ef_info.file_info, &oad_env.file_info, sizeof(struct oad_file_info));
ef_info.file_offset = write_count * OTA_WRITE_FLASH_SIZE;
ef_info.last_wflash_addr = oad_env.w_img_end_addr;
ef_info.upgrd_crc32 = oad_env.upgrd_crc32;
bt_settings_set_bin(NV_IMG_info, (uint8_t *)&ef_info, sizeof(struct oad_ef_info));
BT_WARN("ef_info: file ver(%d) manu code(0x%x) file offset(0x%x) last_adder (0x%x)\r\n", ef_info.file_info.file_ver, ef_info.file_info.manu_code,
ef_info.file_offset, ef_info.last_wflash_addr);
#endif
wData.index = 0;
memcpy((wData.wdata_buf + wData.index), (data + left_size), oDataLen);
wData.index += oDataLen;
}
}
oad_env.upgrd_offset += len;
if (oad_env.upgrd_offset > oad_env.upgrd_file_size) {
return OAD_INVALID_IMAG;
} else if (oad_env.upgrd_offset == oad_env.upgrd_file_size) {
if (wData.index) {
oad_write_flash(oad_env.upgrd_file_size, oad_env.hosal_offset, wData.wdata_buf, wData.index);
}
if (wData.wdata_buf) {
k_free(wData.wdata_buf);
wData.wdata_buf = NULL;
}
return OAD_UPGRD_CMPLT;
} else {
return OAD_REQ_MORE_DATA;
}
}
static void oad_image_info_handler(struct bt_conn *conn, const u8_t *data, u16_t len)
{
oad_notify_image_info(conn);
}
static u8_t oad_image_block_resp_handler(struct bt_conn *conn, const u8_t *data, u16_t len)
{
struct oad_block_rsp_t *block_rsp;
const u8_t *rsp_data;
u8_t status = OAD_SUCC;
switch (*data) {
case OAD_SUCC: {
block_rsp = (struct oad_block_rsp_t *)data;
if (!check_data_valid(&block_rsp->file_info)) {
status = OAD_INVALID_IMAG;
break;
}
if (block_rsp->file_offset != oad_env.upgrd_offset) {
status = OAD_MALORMED_CMD;
break;
}
rsp_data = data + OAD_BLK_RSP_DATA_OFFSET;
status = oad_image_data_handler(conn, rsp_data, block_rsp->data_size);
if (status == OAD_UPGRD_CMPLT) {
oad_notify_upgrd_end(conn, OAD_SUCC);
} else if (status == OAD_REQ_MORE_DATA) {
oad_notify_block_req(conn);
} else {
oad_notify_upgrd_end(conn, status);
}
} break;
case OAD_ABORT: {
#if !defined(CONFIG_BL_MCU_SDK)
bl_flash_erase(oad_env.new_img_addr, oad_env.upgrd_file_size);
#else
flash_erase(oad_env.new_img_addr, oad_env.upgrd_file_size);
#endif
} break;
default:
status = OAD_MALORMED_CMD;
}
return status;
}
static void oad_image_identity_handler(struct bt_conn *conn, const u8_t *data, u16_t len)
{
struct bt_le_conn_param conn_param;
struct oad_image_identity_t *identity = (struct oad_image_identity_t *)(data);
int err = 0;
BT_WARN("File size=[0x%x] [0x%x] [0x%x] [0x%x]\r\n", identity->file_size, identity->file_info.file_ver,
identity->file_info.manu_code, identity->crc32);
#if defined(CONFIG_BT_SETTINGS)
size_t llen = 0;
struct oad_ef_info ef_info;
memset(&ef_info, 0, sizeof(struct oad_ef_info));
bt_settings_get_bin(NV_IMG_info, (uint8_t *)&ef_info, sizeof(struct oad_ef_info), &llen);
BT_WARN("ef_info: file ver(%d) manu code(0x%x) file offset(0x%x) last_adder (0x%x)\r\n", ef_info.file_info.file_ver, ef_info.file_info.manu_code,
ef_info.file_offset, ef_info.last_wflash_addr);
#else
oad_env.new_img_addr = 0;
oad_env.w_img_end_addr = 0;
#endif
if (identity->file_info.manu_code == oad_env.file_info.manu_code &&
(app_check_cb)(oad_env.file_info.file_ver, identity->file_info.file_ver)) {
#if defined(CONFIG_BT_SETTINGS)
if (identity->crc32 && ef_info.upgrd_crc32 == identity->crc32) {
if (ef_info.file_offset && ef_info.file_offset <= identity->file_size) {
oad_env.upgrd_offset = ef_info.file_offset;
}
oad_env.new_img_addr = ef_info.last_wflash_addr;
} else
#endif
{
oad_env.upgrd_offset = 0x00;
}
conn_param.interval_max = 6;
conn_param.interval_min = 6;
conn_param.latency = 0;
conn_param.timeout = 500; //5s
err = bt_conn_le_param_update(conn, &conn_param);
if (err)
BT_WARN("fail to start conn update\r\n");
else
BT_WARN("start conn update\r\n");
oad_env.upgrd_file_ver = identity->file_info.file_ver;
oad_env.upgrd_file_size = identity->file_size;
oad_env.upgrd_crc32 = identity->crc32;
BT_WARN("Send the image block request\r\n");
#if !defined(CONFIG_BL_MCU_SDK)
hosal_ota_start(oad_env.upgrd_file_size);
#endif
oad_notify_block_req(conn);
} else {
oad_notity_image_identity(conn);
}
}
static void oad_recv_callback(struct bt_conn *conn, const u8_t *data, u16_t len)
{
if (len) {
if (*data == OAD_CMD_IMAG_IDENTITY && ((len - 1) == sizeof(struct oad_image_identity_t))) {
oad_image_identity_handler(conn, data + 1, len - 1);
}
if (*data == OAD_CMD_IMAG_BLOCK_RESP) {
oad_image_block_resp_handler(conn, data + 1, len - 1);
}
if (*data == OAD_CMD_IMAG_INFO) {
oad_image_info_handler(conn, data + 1, len - 1);
}
}
}
static void oad_disc_callback(struct bt_conn *conn, u8_t reason)
{
if (wData.wdata_buf) {
k_free(wData.wdata_buf);
wData.wdata_buf = NULL;
wData.index = 0;
}
}
#if defined(CONFIG_BL_MCU_SDK)
static struct {
u8_t partition_active_idx;
u8_t pad[3];
pt_table_stuff_config table;
} boot2_partition_table;
//#define PARTITION_MAGIC (0x54504642)
pt_table_id_type active_id = PT_TABLE_ID_INVALID;
pt_table_stuff_config pt_table_stuff[2];
static int fw_check_hash256(void)
{
uint32_t bin_size;
uint32_t hash_addr;
pt_table_entry_config ptEntry;
if (oad_env.upgrd_file_size <= 32) {
return -1;
}
if (oad_env.w_img_end_addr <= 32) {
return -1;
}
bin_size = oad_env.upgrd_file_size - 32;
hash_addr = oad_env.w_img_end_addr - 32;
if (hal_boot2_get_active_entries_byname((uint8_t *)"FW", &ptEntry)) {
BT_WARN("Failed to get active entries by name\r\n");
return -1;
}
#define CHECK_IMG_BUF_SIZE 512
uint8_t sha_check[32] = { 0 };
uint8_t dst_sha[32] = { 0 };
uint32_t read_size;
mbedtls_sha256_context sha256_ctx;
int i, offset = 0;
uint8_t r_buf[CHECK_IMG_BUF_SIZE];
BT_WARN("[OTA]prepare OTA partition info\r\n");
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha256_starts_ret(&sha256_ctx, 0);
memset(sha_check, 0, 32);
memset(dst_sha, 0, 32);
offset = 0;
while (offset < bin_size) {
(bin_size - offset >= CHECK_IMG_BUF_SIZE) ? (read_size = CHECK_IMG_BUF_SIZE) : (read_size = bin_size - offset);
if (flash_read(oad_env.new_img_addr + offset, r_buf, read_size)) {
BT_WARN("flash read failed \r\n");
return -1;
}
mbedtls_sha256_update_ret(&sha256_ctx, (const uint8_t *)r_buf, read_size);
offset += read_size;
}
mbedtls_sha256_finish_ret(&sha256_ctx, sha_check);
flash_read(hash_addr, dst_sha, 32);
for (i = 0; i < 32; i++) {
BT_WARN("%02X", dst_sha[i]);
}
puts("\r\nHeader SET SHA256 Checksum:");
for (i = 0; i < 32; i++) {
BT_WARN("%02X", sha_check[i]);
}
if (memcmp(sha_check, (const void *)dst_sha, 32) != 0) {
BT_WARN("sha256 check error\r\n");
return -1;
}
ptEntry.len = bin_size;
BT_WARN("[OTA] Update PARTITION, partition len is %lu\r\n", ptEntry.len);
hal_boot2_update_ptable(&ptEntry);
return 0;
}
static int oad_hal_boot2_partition_addr(const char *name, uint32_t *addr0, uint32_t *addr1, uint32_t *size0, uint32_t *size1, int *active)
{
int i;
if (BFLB_PT_MAGIC_CODE != boot2_partition_table.table.pt_table.magicCode) {
return -EIO;
}
/*Get Target partition*/
for (i = 0; i < boot2_partition_table.table.pt_table.entryCnt; i++) {
if (0 == strcmp((char *)&(boot2_partition_table.table.pt_entries[i].name[0]), name)) {
break;
}
}
if (boot2_partition_table.table.pt_table.entryCnt == i) {
return -ENOENT;
}
*addr0 = boot2_partition_table.table.pt_entries[i].start_address[0];
*addr1 = boot2_partition_table.table.pt_entries[i].start_address[1];
*size0 = boot2_partition_table.table.pt_entries[i].max_len[0];
*size1 = boot2_partition_table.table.pt_entries[i].max_len[1];
*active = boot2_partition_table.table.pt_entries[i].active_index;
return 0;
}
static int hal_boot2_partition_addr_inactive(const char *name, uint32_t *addr, uint32_t *size)
{
uint32_t addr0, addr1;
uint32_t size0, size1;
int active, ret;
if ((ret = oad_hal_boot2_partition_addr(name, &addr0, &addr1, &size0, &size1, &active))) {
return ret;
}
*addr = active ? addr0 : addr1;
*size = active ? size0 : size1;
return 0;
}
static pt_table_error_type oad_PtTable_Get_Active_Entries_By_Name(pt_table_stuff_config *ptStuff,
u8_t *name,
pt_table_entry_config *ptEntry)
{
uint32_t i = 0;
uint32_t len = strlen((char *)name);
if (ptStuff == NULL || ptEntry == NULL) {
return PT_ERROR_PARAMETER;
}
for (i = 0; i < ptStuff->pt_table.entryCnt; i++) {
if (strlen((char *)ptStuff->pt_entries[i].name) == len &&
memcmp((char *)ptStuff->pt_entries[i].name, (char *)name, len) == 0) {
ARCH_MemCpy_Fast(ptEntry, &ptStuff->pt_entries[i], sizeof(pt_table_entry_config));
return PT_ERROR_SUCCESS;
}
}
return PT_ERROR_ENTRY_NOT_FOUND;
}
static int hal_boot2_update_ptable(pt_table_entry_config *ptEntry_hal)
{
int ret;
//FIXME force covert
pt_table_entry_config *ptEntry = (pt_table_entry_config *)ptEntry_hal;
ptEntry->active_index = !ptEntry->active_index;
(ptEntry->age)++;
ret = pt_table_update_entry((pt_table_id_type)(!active_id), &pt_table_stuff[!active_id], ptEntry);
return ret;
}
static int hal_boot2_get_active_entries_byname(uint8_t *name, pt_table_entry_config *ptEntry_hal)
{
pt_table_entry_config *ptEntry = (pt_table_entry_config *)ptEntry_hal;
if (oad_PtTable_Get_Active_Entries_By_Name(&boot2_partition_table.table, name, ptEntry)) {
return -1;
}
return 0;
}
static int oad_get_boot2_partition_table(void)
{
memcpy(&boot2_partition_table.table, &pt_table_stuff[active_id], sizeof(pt_table_stuff_config));
boot2_partition_table.partition_active_idx = active_id;
BT_WARN("magicCode: 0x%x\r\n", boot2_partition_table.table.pt_table.magicCode);
return 0;
}
#endif
void oad_service_enable(app_check_oad_cb cb)
{
//todo: get current file info for oad_env.fileinfo
app_check_cb = cb;
oad_env.file_info.file_ver = LOCAL_FILE_VER;
oad_env.file_info.manu_code = LOCAL_MANU_CODE;
oad_env.new_img_addr = 0;
bt_oad_service_enable();
bt_oad_register_recv_cb(oad_recv_callback);
bt_oad_register_disc_cb(oad_disc_callback);
#if defined(CONFIG_BL_MCU_SDK)
flash_init();
pt_table_set_flash_operation(flash_erase, flash_write, flash_read);
active_id = pt_table_get_active_partition_need_lock(pt_table_stuff);
oad_get_boot2_partition_table();
#endif
k_delayed_work_init(&oad_env.upgrd_work, ota_finish);
}

View File

@@ -22,7 +22,7 @@ NOTES
#include "uuid.h"
#include "ble_peripheral_tp_server.h"
#include "log.h"
#include "bl702_glb.h"
static void ble_tp_connected(struct bt_conn *conn, u8_t err);
static void ble_tp_disconnected(struct bt_conn *conn, u8_t reason);

View File

@@ -0,0 +1,352 @@
/****************************************************************************
FILE NAME
ble_peripheral_tp_server.c
DESCRIPTION
test profile demo
NOTES
*/
/****************************************************************************/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <FreeRTOS.h>
#include <task.h>
#include "bluetooth.h"
#include "conn.h"
#include "gatt.h"
#include "hci_core.h"
#include "uuid.h"
#include "ble_peripheral_tp_server.h"
#include "log.h"
#include "hal_clock.h"
extern bool pds_start;
static void ble_tp_connected(struct bt_conn *conn, u8_t err);
static void ble_tp_disconnected(struct bt_conn *conn, u8_t reason);
static void ble_param_updated(struct bt_conn *conn, u16_t interval, u16_t latency, u16_t timeout);
static struct bt_conn *ble_tp_conn;
#if !defined(CONFIG_BT_OAD_SERVER)
static struct bt_gatt_exchange_params exchg_mtu;
#endif
static TaskHandle_t ble_tp_task_h;
static struct k_sem notify_poll_sem;
static int tx_mtu_size = 20;
static u8_t created_tp_task = 0;
static u8_t isRegister = 0;
static struct bt_conn_cb ble_tp_conn_callbacks = {
.connected = ble_tp_connected,
.disconnected = ble_tp_disconnected,
.le_param_updated = ble_param_updated,
};
#if !defined(CONFIG_BT_OAD_SERVER)
/*************************************************************************
NAME
ble_tp_tx_mtu_size
*/
static void ble_tp_tx_mtu_size(struct bt_conn *conn, u8_t err,
struct bt_gatt_exchange_params *params)
{
if (!err) {
tx_mtu_size = bt_gatt_get_mtu(ble_tp_conn);
BT_WARN("ble tp echange mtu size success, mtu size: %d", tx_mtu_size);
} else {
BT_WARN("ble tp echange mtu size failure, err: %d", err);
}
}
#endif
/*************************************************************************
NAME
ble_tp_connected
*/
static void ble_tp_connected(struct bt_conn *conn, u8_t err)
{
#if !defined(CONFIG_BT_OAD_SERVER)
int tx_octets = 0x00fb;
int tx_time = 0x0848;
int ret = -1;
#endif
#if XTAL_32K_TYPE == EXTERNAL_XTAL_32K
struct bt_le_conn_param param;
#endif
if (err) {
return;
}
BT_WARN("Tp connected");
ble_tp_conn = conn;
pds_start = false;
#if XTAL_32K_TYPE == EXTERNAL_XTAL_32K
param.interval_min = param.interval_max = 0x320;
param.latency = 0;
param.timeout = 0x05dc;
ret = bt_conn_le_param_update(ble_tp_conn, &param);
if (ret) {
BT_WARN("conn update failed (err %d)\r\n", ret);
} else {
BT_WARN("conn update initiated\r\n");
}
#endif
#if !defined(CONFIG_BT_OAD_SERVER)
//set data length after connected.
ret = bt_le_set_data_len(ble_tp_conn, tx_octets, tx_time);
if (!ret) {
BT_WARN("ble tp set data length success");
} else {
BT_WARN("ble tp set data length failure, err: %d", ret);
}
//exchange mtu size after connected.
exchg_mtu.func = ble_tp_tx_mtu_size;
ret = bt_gatt_exchange_mtu(ble_tp_conn, &exchg_mtu);
if (!ret) {
BT_WARN("ble tp exchange mtu size pending");
} else {
BT_WARN("ble tp exchange mtu size failure, err: %d", ret);
}
#endif
}
/*************************************************************************
NAME
ble_tp_disconnected
*/
static void ble_tp_disconnected(struct bt_conn *conn, u8_t reason)
{
BT_WARN("Tp disconnected");
if (created_tp_task) {
BT_WARN("Delete throughput tx task");
vTaskDelete(ble_tp_task_h);
created_tp_task = 0;
}
ble_tp_conn = NULL;
extern int ble_start_adv(void);
ble_start_adv();
pds_start = true;
}
/*************************************************************************
NAME
ble_param_updated
*/
static void ble_param_updated(struct bt_conn *conn, u16_t interval,
u16_t latency, u16_t timeout)
{
BT_WARN("LE conn param updated: int 0x%04x lat %d to %d \r\n", interval, latency, timeout);
#if XTAL_32K_TYPE == EXTERNAL_XTAL_32K
if (interval > 80) {
pds_start = true;
} else {
pds_start = false;
}
#endif
}
/*************************************************************************
NAME
ble_tp_recv_rd
*/
static int ble_tp_recv_rd(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, u16_t len, u16_t offset)
{
int size = 9;
char data[9] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
memcpy(buf, data, size);
return size;
}
/*************************************************************************
NAME
ble_tp_recv_wr(receive data from client)
*/
static int ble_tp_recv_wr(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *buf, u16_t len, u16_t offset, u8_t flags)
{
BT_WARN("recv data len=%d, offset=%d, flag=%d", len, offset, flags);
BT_WARN("recv data:%s", bt_hex(buf, len));
if (flags & BT_GATT_WRITE_FLAG_PREPARE) {
//Don't use prepare write data, execute write will upload data again.
BT_WARN("recv prepare write request");
return 0;
}
if (flags & BT_GATT_WRITE_FLAG_CMD) {
//Use write command data.
BT_WARN("recv write command");
} else {
//Use write request / execute write data.
BT_WARN("recv write request / exce write");
}
k_sem_give(&notify_poll_sem);
return len;
}
/*************************************************************************
NAME
indicate_rsp /bl_tp_send_indicate
*/
static void indicate_rsp(struct bt_conn *conn, const struct bt_gatt_attr *attr, u8_t err)
{
BT_WARN("receive comfirmation, err:%d", err);
}
static int bl_tp_send_indicate(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *data, u16_t len)
{
static struct bt_gatt_indicate_params ind_params;
ind_params.attr = attr;
ind_params.data = data;
ind_params.len = len;
ind_params.func = indicate_rsp;
ind_params.uuid = NULL;
return bt_gatt_indicate(conn, &ind_params);
}
/*************************************************************************
NAME
ble_tp_ind_ccc_changed
*/
static void ble_tp_ind_ccc_changed(const struct bt_gatt_attr *attr, u16_t value)
{
int err = -1;
char data[9] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
if (value == BT_GATT_CCC_INDICATE) {
err = bl_tp_send_indicate(ble_tp_conn, get_attr(BT_CHAR_BLE_TP_IND_ATTR_VAL_INDEX), data, 9);
BT_WARN("ble tp send indatcate: %d", err);
}
}
/*************************************************************************
NAME
ble_tp_notify(send data to client)
*/
static void ble_tp_notify_task(void *pvParameters)
{
int err = -1;
u8_t data[244] = { 0x01 };
k_sem_give(&notify_poll_sem);
while (1) {
k_sem_take(&notify_poll_sem, K_FOREVER);
//send data to client
err = bt_gatt_notify(ble_tp_conn, get_attr(BT_CHAR_BLE_TP_NOT_ATTR_VAL_INDEX), data, (tx_mtu_size - 3));
data[0] = data[0] + 1;
BT_WARN("ble tp send notify : %d", err);
}
}
/*************************************************************************
NAME
ble_tp_not_ccc_changed
*/
static void ble_tp_notify_ccc_changed(const struct bt_gatt_attr *attr, u16_t value)
{
BT_WARN("ccc:value=[%d]", value);
if (value == BT_GATT_CCC_NOTIFY) {
if (xTaskCreate(ble_tp_notify_task, (char *)"bletp", 512, NULL, 15, &ble_tp_task_h) == pdPASS) {
created_tp_task = 1;
BT_WARN("Create throughput tx task success");
} else {
created_tp_task = 0;
BT_WARN("Create throughput tx taskfail");
}
} else {
if (created_tp_task) {
BT_WARN("Delete throughput tx task");
vTaskDelete(ble_tp_task_h);
created_tp_task = 0;
}
}
}
/*************************************************************************
* DEFINE : attrs
*/
static struct bt_gatt_attr attrs[] = {
BT_GATT_PRIMARY_SERVICE(BT_UUID_SVC_BLE_TP),
BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_RD,
BT_GATT_CHRC_READ,
BT_GATT_PERM_READ,
ble_tp_recv_rd,
NULL,
NULL),
BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_WR,
BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_WRITE | BT_GATT_PERM_PREPARE_WRITE,
NULL,
ble_tp_recv_wr,
NULL),
BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_IND,
BT_GATT_CHRC_INDICATE,
0,
NULL,
NULL,
NULL),
BT_GATT_CCC(ble_tp_ind_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_NOT,
BT_GATT_CHRC_NOTIFY,
0,
NULL,
NULL,
NULL),
BT_GATT_CCC(ble_tp_notify_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)
};
/*************************************************************************
NAME
get_attr
*/
struct bt_gatt_attr *get_attr(u8_t index)
{
return &attrs[index];
}
static struct bt_gatt_service ble_tp_server = BT_GATT_SERVICE(attrs);
/*************************************************************************
NAME
ble_tp_init
*/
void ble_tp_init()
{
if (!isRegister) {
isRegister = 1;
bt_conn_cb_register(&ble_tp_conn_callbacks);
bt_gatt_service_register(&ble_tp_server);
k_sem_init(&notify_poll_sem, 0, 1);
}
}

View File

@@ -0,0 +1,38 @@
/****************************************************************************
FILE NAME
ble_peripheral_tp_server.h
DESCRIPTION
NOTES
*/
/****************************************************************************/
#ifndef _BLE_TP_SVC_H_
#define _BLE_TP_SVC_H_
#include "ble_config.h"
//07af27a5-9c22-11ea-9afe-02fcdc4e7412
#define BT_UUID_SVC_BLE_TP BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a5, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412))
//07af27a6-9c22-11ea-9afe-02fcdc4e7412
#define BT_UUID_CHAR_BLE_TP_RD BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a6, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412))
//07af27a7-9c22-11ea-9afe-02fcdc4e7412
#define BT_UUID_CHAR_BLE_TP_WR BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a7, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412))
//07af27a8-9c22-11ea-9afe-02fcdc4e7412
#define BT_UUID_CHAR_BLE_TP_IND BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a8, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412))
//07af27a9-9c22-11ea-9afe-02fcdc4e7412
#define BT_UUID_CHAR_BLE_TP_NOT BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a9, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412))
//read value handle offset 2
#define BT_CHAR_BLE_TP_RD_ATTR_VAL_INDEX (2)
//write value handle offset 4
#define BT_CHAR_BLE_TP_WR_ATTR_VAL_INDEX (4)
//indicate value handle offset 6
#define BT_CHAR_BLE_TP_IND_ATTR_VAL_INDEX (6)
//notity value handle offset 9
#define BT_CHAR_BLE_TP_NOT_ATTR_VAL_INDEX (9)
void ble_tp_init();
struct bt_gatt_attr *get_attr(u8_t index);
#endif