- app_ota.c: after END ok, wait until the RSP is consumed by the host (BLE e0005 read-out / UART TX done) plus 300ms grace before resetting, 2s timeout fallback; polled from the BLE schedule task (rwip_schedule must keep running for the ATT read to be processed) - main.c: app_ota_reset_poll() in the BLE schedule task loop - docs: ble_protocol.md 6.6 note, dev log section 43, AGENTS.md sync
384 lines
15 KiB
C
384 lines
15 KiB
C
/**
|
|
* Copyright (c) 2025, NSING Technologies Inc.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* This software is the exclusive property of NSING Technologies Inc. (Hereinafter
|
|
* referred to as NSING). This software, and the product of NSING described herein
|
|
* (Hereinafter referred to as the Product) are owned by NSING under the laws and treaties
|
|
* of the People's Republic of China and other applicable jurisdictions worldwide.
|
|
*
|
|
* NSING does not grant any license under its patents, copyrights, trademarks, or other
|
|
* intellectual property rights. Names and brands of third party may be mentioned or referred
|
|
* thereto (if any) for identification purposes only.
|
|
*
|
|
* NSING reserves the right to make changes, corrections, enhancements, modifications, and
|
|
* improvements to this software at any time without notice. Please contact NSING and obtain
|
|
* the latest version of this software before placing orders.
|
|
|
|
* Although NSING has attempted to provide accurate and reliable information, NSING assumes
|
|
* no responsibility for the accuracy and reliability of this software.
|
|
*
|
|
* It is the responsibility of the user of this software to properly design, program, and test
|
|
* the functionality and safety of any application made of this information and any resulting product.
|
|
* In no event shall NSING be liable for any direct, indirect, incidental, special,exemplary, or
|
|
* consequential damages arising in any way out of the use of this software or the Product.
|
|
*
|
|
* NSING Products are neither intended nor warranted for usage in systems or equipment, any
|
|
* malfunction or failure of which may cause loss of human life, bodily injury or severe property
|
|
* damage. Such applications are deemed, "Insecure Usage".
|
|
*
|
|
* All Insecure Usage shall be made at user's risk. User shall indemnify NSING and hold NSING
|
|
* harmless from and against all claims, costs, damages, and other liabilities, arising from or related
|
|
* to any customer's Insecure Usage.
|
|
|
|
* Any express or implied warranty with regard to this software or the Product, including,but not
|
|
* limited to, the warranties of merchantability, fitness for a particular purpose and non-infringement
|
|
* are disclaimed to the fullest extent permitted by law.
|
|
|
|
* Unless otherwise explicitly permitted by NSING, anyone may not duplicate, modify, transcribe
|
|
* or otherwise distribute this software for any purposes, in whole or in part.
|
|
*
|
|
* NSING products and technologies shall not be used for or incorporated into any products or systems
|
|
* whose manufacture, use, or sale is prohibited under any applicable domestic or foreign laws or regulations.
|
|
* User shall comply with any applicable export control laws and regulations promulgated and administered by
|
|
* the governments of any countries asserting jurisdiction over the parties or transactions.
|
|
**/
|
|
|
|
|
|
/**
|
|
* @file app_rdtss.c
|
|
* @author NSING Firmware Team
|
|
* @version v1.0.1
|
|
*
|
|
* @copyright Copyright (c) 2025, NSING Technologies Inc. All rights reserved.
|
|
*/
|
|
|
|
/**
|
|
* @addtogroup APP
|
|
* @{
|
|
*/
|
|
|
|
#include "rwip_config.h" // SW configuration
|
|
|
|
#if (BLE_RDTSS_SERVER)
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include "co_utils.h"
|
|
#include "app_rdtss.h" // rdtss Application Module Definitions
|
|
#include "rdtss_task.h" // Device Information Profile Functions
|
|
#include "gapm_task.h" // GAP Manager Task API
|
|
#include "ns_ble.h"
|
|
#include "prf.h"
|
|
#include "ke_timer.h"
|
|
#include "stdio.h"
|
|
#include "rdtss.h"
|
|
#include "app_ble_proto.h"
|
|
#include "app_info.h"
|
|
#include "app_ota.h"
|
|
#include "ble_up.h"
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
/* Private constants ---------------------------------------------------------*/
|
|
/* Private variables ---------------------------------------------------------*/
|
|
uint8_t notify_en = 0;
|
|
const uint8_t app_rdts_svc_uuid[16] = ATT_SERVICE_AM_SPEED_128;
|
|
const struct attm_desc_128 app_rdts_att_db[RDTSS_IDX_NB] =
|
|
{
|
|
/* Service Declaration */
|
|
[0] = {{0x00,0x28}, PERM(RD, ENABLE), 0, 0 },
|
|
|
|
/* Characteristic Declaration */
|
|
[1] = {{0x03,0x28}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0 },
|
|
/* Characteristic Value */
|
|
[2] = {ATT_CHAR_AM_SPEED_WRITE_128, PERM(WRITE_COMMAND, ENABLE), PERM(RI, ENABLE)| PERM_VAL(UUID_LEN, 0x02), 0x200 },
|
|
/* Client Characteristic Configuration Descriptor */
|
|
[3] = {{0x01,0x29}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), PERM(RI, ENABLE), 20 },
|
|
|
|
/* Characteristic Declaration */
|
|
[4] = {{0x03,0x28}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0 },
|
|
/* Characteristic Value */
|
|
[5] = {ATT_CHAR_AM_SPEED_NTF_128, PERM(NTF, ENABLE), PERM(RI, ENABLE)| PERM_VAL(UUID_LEN, 0x02), 0x200 },
|
|
/* Client Characteristic Configuration Descriptor */
|
|
[6] = {{0x02,0x29}, PERM(RD, ENABLE) |PERM(WRITE_REQ, ENABLE), PERM(RI, ENABLE), 20 },
|
|
|
|
/* Characteristic Declaration */
|
|
[7] = {{0x03,0x28}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0 },
|
|
/* CLI Characteristic Value: raw command line in (write-with-response),
|
|
* command output text out (sequential chunked reads, 0-length = EOF) */
|
|
[8] = {ATT_CHAR_AM_SPEED_CLI_128, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), PERM(RI, ENABLE)| PERM_VAL(UUID_LEN, 0x02), 0x200 },
|
|
|
|
/* Characteristic Declaration */
|
|
[9] = {{0x03,0x28}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0 },
|
|
/* Device info Characteristic Value (read-only): TLV snapshot of all
|
|
* info items, identical content to an INFO_RSP(all) frame */
|
|
[10] = {ATT_CHAR_AM_SPEED_INFO_128, PERM(RD, ENABLE), PERM(RI, ENABLE)| PERM_VAL(UUID_LEN, 0x02), 0x200 },
|
|
|
|
/* Characteristic Declaration */
|
|
[11] = {{0x03,0x28}, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0 },
|
|
/* OTA Characteristic Value: one 0xCA transport frame in
|
|
* (write-with-response), the OTA_RSP frame out (ATT read) */
|
|
[12] = {ATT_CHAR_AM_SPEED_OTA_128, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), PERM(RI, ENABLE)| PERM_VAL(UUID_LEN, 0x02), 0x200 },
|
|
};
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
|
|
/**
|
|
* @brief Create raw data transfer server profile database.
|
|
* @return void
|
|
*/
|
|
void app_rdtss_add_rdts(void)
|
|
{
|
|
struct rdtss_db_cfg *db_cfg;
|
|
|
|
struct gapm_profile_task_add_cmd *req = KE_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD,
|
|
TASK_GAPM,
|
|
TASK_APP,
|
|
gapm_profile_task_add_cmd,
|
|
sizeof(struct rdtss_db_cfg));
|
|
|
|
// Fill message
|
|
req->operation = GAPM_PROFILE_TASK_ADD;
|
|
req->sec_lvl = PERM(SVC_AUTH, NO_AUTH);
|
|
req->prf_task_id = TASK_ID_RDTSS;
|
|
req->app_task = TASK_APP;
|
|
req->start_hdl = 0;
|
|
|
|
// Set parameters
|
|
db_cfg = (struct rdtss_db_cfg *) req->param;
|
|
// Attribute table. In case the handle offset needs to be saved
|
|
db_cfg->att_tbl = &app_rdts_att_db[0];
|
|
db_cfg->svc_uuid = &app_rdts_svc_uuid[0];
|
|
db_cfg->max_nb_att = RDTSS_IDX_NB;
|
|
|
|
// Send the message
|
|
ke_msg_send(req);
|
|
|
|
app_rdtss_init();
|
|
}
|
|
|
|
/**
|
|
* @brief rdtss value require indicate handler
|
|
* @param
|
|
* @return
|
|
* @note Note
|
|
*/
|
|
static int rdtss_value_req_ind_handler(ke_msg_id_t const msgid,
|
|
struct rdtss_value_req_ind const *req_value,
|
|
ke_task_id_t const dest_id,
|
|
ke_task_id_t const src_id)
|
|
{
|
|
NS_LOG_DEBUG("%s\r\n",__func__);
|
|
|
|
// Initialize length
|
|
uint16_t len = 0;
|
|
// Pointer to the data
|
|
const uint8_t *data = NULL;
|
|
|
|
if (req_value->att_idx == RDTSS_IDX_CLI_VAL)
|
|
{
|
|
// CLI read/write characteristic: return the last command's output text
|
|
data = app_ble_proto_cli_rsp(&len);
|
|
}
|
|
else if (req_value->att_idx == RDTSS_IDX_OTA_VAL)
|
|
{
|
|
// OTA channel: fetch the pending framed OTA_RSP (consumed on read)
|
|
data = app_ota_chan_rsp_ble(&len);
|
|
}
|
|
else if (req_value->att_idx == RDTSS_IDX_INFO_VAL)
|
|
{
|
|
// device info characteristic: TLV snapshot of all info items
|
|
data = app_info_tlv_snapshot(&len);
|
|
}
|
|
else
|
|
{
|
|
len = APP_RDTSS_MANUFACTURER_NAME_LEN;
|
|
data = (uint8_t *)APP_RDTSS_MANUFACTURER_NAME;
|
|
}
|
|
// Allocate confirmation to send the value
|
|
struct rdtss_value_req_rsp *rsp_value = KE_MSG_ALLOC_DYN(RDTSS_VALUE_REQ_RSP,
|
|
src_id, dest_id,
|
|
rdtss_value_req_rsp,
|
|
len);
|
|
rsp_value->status = 0;
|
|
rsp_value->conidx = req_value ->conidx;
|
|
rsp_value->length = len;
|
|
rsp_value->att_idx = req_value->att_idx;
|
|
if (len)
|
|
{
|
|
// Copy data
|
|
memcpy(&rsp_value->value, data, len);
|
|
}
|
|
// Send message
|
|
ke_msg_send(rsp_value);
|
|
|
|
return (KE_MSG_CONSUMED);
|
|
}
|
|
|
|
/**
|
|
* @brief cuusts write indicate handler
|
|
* @param
|
|
* @return
|
|
* @note
|
|
*/
|
|
static int rdtss_val_write_ind_handler(ke_msg_id_t const msgid,
|
|
struct rdtss_val_write_ind const *ind_value,
|
|
ke_task_id_t const dest_id,
|
|
ke_task_id_t const src_id)
|
|
{
|
|
uint16_t handle = ind_value->handle;
|
|
uint16_t length = ind_value->length;
|
|
|
|
/* Raw write dump, gated by the "blelog" CLI switch (the former NS_LOG_DEBUG
|
|
* dump was compiled out, leaving the downlink path completely silent) */
|
|
if (app_ble_proto_log_get())
|
|
{
|
|
uint16_t i;
|
|
uint16_t n = (length > 24) ? 24 : length;
|
|
printf("[BLE] write ind: att_idx=%u len=%u", handle, length);
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
printf(" %02X", ind_value->value[i]);
|
|
}
|
|
if (length > n)
|
|
{
|
|
printf(" ...");
|
|
}
|
|
printf("\r\n");
|
|
}
|
|
|
|
switch (handle)
|
|
{
|
|
case RDTSS_IDX_NTF_CFG:
|
|
|
|
if(length == 2)
|
|
{
|
|
uint16_t cfg_value = (uint16_t)ind_value->value[0] |
|
|
((uint16_t)ind_value->value[1] << 8);
|
|
|
|
if(cfg_value == PRF_CLI_START_NTF)
|
|
{
|
|
//enabled notify
|
|
notify_en = 1;
|
|
if (app_ble_proto_log_get())
|
|
{
|
|
printf("[BLE] notify enabled\r\n");
|
|
}
|
|
}
|
|
else if(cfg_value == PRF_CLI_STOP_NTFIND)
|
|
{
|
|
notify_en = 0;
|
|
if (app_ble_proto_log_get())
|
|
{
|
|
printf("[BLE] notify disabled\r\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
case RDTSS_IDX_WRITE_VAL:
|
|
//ble data receive -> frame reassembler (CLI_REQ etc.)
|
|
app_ble_proto_rx_bytes(ind_value->value, ind_value->length);
|
|
|
|
break;
|
|
case RDTSS_IDX_CLI_VAL:
|
|
// raw CLI command line (write-with-response); output is fetched
|
|
// back through an ATT read of this same characteristic
|
|
app_ble_proto_cli_exec(ind_value->value, ind_value->length);
|
|
|
|
break;
|
|
case RDTSS_IDX_OTA_VAL:
|
|
// OTA transport frame (write-with-response); the OTA_RSP frame is
|
|
// fetched back through an ATT read of this same characteristic
|
|
app_ota_chan_rx_ble(ind_value->value, ind_value->length);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
return (KE_MSG_CONSUMED);
|
|
}
|
|
|
|
/**
|
|
* @brief Functions
|
|
* @param
|
|
* @return
|
|
* @note Note
|
|
*/
|
|
static int rdtss_val_ntf_cfm_handler(ke_msg_id_t const msgid,
|
|
struct rdtss_val_ntf_cfm const *cfm_value,
|
|
ke_task_id_t const dest_id,
|
|
ke_task_id_t const src_id)
|
|
{
|
|
NS_LOG_DEBUG("%s,ntf cfm handle = %x, status = %x\r\n",__func__, cfm_value->handle, cfm_value->status);
|
|
|
|
ble_up_on_cfm();
|
|
|
|
return (KE_MSG_CONSUMED);
|
|
}
|
|
|
|
/**
|
|
* @brief rdtss send notify
|
|
* @param
|
|
* @return
|
|
* @note
|
|
*/
|
|
void rdtss_send_notify(uint8_t *data, uint16_t length)
|
|
{
|
|
if (notify_en)
|
|
{
|
|
struct rdtss_val_ntf_ind_req *req = KE_MSG_ALLOC_DYN(RDTSS_VAL_NTF_REQ,
|
|
prf_get_task_from_id(TASK_ID_RDTSS),
|
|
TASK_APP,
|
|
rdtss_val_ntf_ind_req,
|
|
length);
|
|
|
|
req->conidx = app_env.conidx;
|
|
req->notification = true;
|
|
req->handle = RDTSS_IDX_NTF_VAL;
|
|
req->length = length;
|
|
memcpy(&req->value[0], data, length);
|
|
|
|
ke_msg_send(req);
|
|
}
|
|
else
|
|
{
|
|
NS_LOG_INFO("Not enable notify\r\n");
|
|
}
|
|
}
|
|
|
|
|
|
/// Default State handlers definition
|
|
const struct ke_msg_handler app_rdtss_msg_handler_list[] =
|
|
{
|
|
{RDTSS_VALUE_REQ_IND, (ke_msg_func_t)rdtss_value_req_ind_handler},
|
|
{RDTSS_VAL_WRITE_IND, (ke_msg_func_t)rdtss_val_write_ind_handler},
|
|
{RDTSS_VAL_NTF_CFM, (ke_msg_func_t)rdtss_val_ntf_cfm_handler},
|
|
|
|
};
|
|
|
|
const struct app_subtask_handlers app_rdtss_handlers = APP_HANDLERS(app_rdtss);
|
|
|
|
|
|
void app_rdtss_init(void)
|
|
{
|
|
//register application subtask to app task
|
|
struct prf_task_t prf;
|
|
prf.prf_task_id = TASK_ID_RDTSS;
|
|
prf.prf_task_handler = &app_rdtss_handlers;
|
|
ns_ble_prf_task_register(&prf);
|
|
|
|
//register get itf function to prf.c
|
|
struct prf_get_func_t get_func;
|
|
get_func.task_id = TASK_ID_RDTSS;
|
|
get_func.prf_itf_get_func = rdtss_prf_itf_get;
|
|
prf_get_itf_func_register(&get_func);
|
|
}
|
|
|
|
#endif //BLE_RDTSS_SERVER
|