생산용 BLE write 명령 잠금 추가

- serial number / HW version / passkey write 명령 해당
- production_done NVS 플래그 추가
- 기존 passkey_changed 플래그 제거
- production_done=0 상태에서만 Serial/HW/Passkey Write 허용
- production_done=1 상태에서는 생산용 Write 명령을 rxd 응답으로 차단
- msr 본딩 삭제 성공 시 production_done=1 저장
This commit is contained in:
2026-07-30 11:51:06 +09:00
parent 41137a1c72
commit eab562d52e
6 changed files with 70 additions and 47 deletions
+25 -13
View File
@@ -12,6 +12,7 @@
#include "cmd_common.h"
#include "main.h"
#include "debug_print.h"
#include "app_nvs.h"
#include "ble_service.h"
#include "cmd_device.h"
#include "led_control.h"
@@ -64,15 +65,6 @@ int cmd_msr(const uint8_t *data, uint8_t data_len)
ARG_UNUSED(data);
ARG_UNUSED(data_len);
int tx_err = cmd_send_response_u16("rsr:", status);
if (tx_err)
{
DBG_ERR("[CMD] msr tx failed err=%d\r\n", tx_err);
return 1;
}
k_msleep(100);
#if IS_ENABLED(CONFIG_BT_SMP)
int err = bt_unpair(BT_ID_DEFAULT, NULL);
if (err)
@@ -82,10 +74,9 @@ int cmd_msr(const uint8_t *data, uint8_t data_len)
}
else
{
led_set_state(LED_STATE_BOND_DELETE); // 삭제 완료 확인 주황 LED ON
led_set_state(LED_STATE_BOND_DELETE);
bond_data_delete = true;
DBG_PRINTF("[CMD] msr bond data deleted\r\n");
k_msleep(1500);
}
#else
bond_data_delete = true;
@@ -94,13 +85,34 @@ int cmd_msr(const uint8_t *data, uint8_t data_len)
if (status == 0x0000)
{
DBG_PRINTF("[CMD] msr complete -> reboot\r\n");
int nvs_err = app_nvs_save_production_done(1U);
if (nvs_err)
{
status = (uint16_t)(-nvs_err);
DBG_ERR("[CMD] msr production_done save failed err=%d\r\n", nvs_err);
}
else
{
m_production_done = 1U;
}
}
int tx_err = cmd_send_response_u16("rsr:", status);
if (tx_err)
{
DBG_ERR("[CMD] msr tx failed err=%d\r\n", tx_err);
return 1;
}
if (status == 0x0000)
{
DBG_PRINTF("[CMD] msr complete -> production done, reboot\r\n");
k_msleep(1500);
}
cmd_reboot_after_response();
return 1;
}
/*
* mdf: DFU mode enter
*/
+28 -15
View File
@@ -11,6 +11,19 @@
#include "app_nvs.h"
#include "cmd_info.h"
/* Production Mode - Serial Number, HW Version, Passkey write command lock */
static bool cmd_info_write_locked(const char *cmd_tag)
{
if (m_production_done == 0U)
{
return false;
}
cmd_send_response_tag_echo("rxd:", cmd_tag);
DBG_PRINTF("[CMD] production write disabled: %s\r\n", cmd_tag);
return true;
}
/*
* mfv: firmware version read
*/
@@ -54,6 +67,11 @@ int cmd_mid(const uint8_t *data, uint8_t data_len)
*/
int cmd_mwh(const uint8_t *data, uint8_t data_len)
{
if (cmd_info_write_locked("mwh?"))
{
return 1;
}
if (data_len < HW_NO_LENGTH)
{
cmd_send_response_u16("rwh:", 0xFFFF);
@@ -96,6 +114,11 @@ int cmd_mrh(const uint8_t *data, uint8_t data_len)
*/
int cmd_mws(const uint8_t *data, uint8_t data_len)
{
if (cmd_info_write_locked("mws?"))
{
return 1;
}
if (data_len < SERIAL_NO_LENGTH)
{
cmd_send_response_u16("rws:", 0xFFFF);
@@ -138,19 +161,17 @@ int cmd_mrs(const uint8_t *data, uint8_t data_len)
*/
int cmd_mpz(const uint8_t *data, uint8_t data_len)
{
if (cmd_info_write_locked("mpz?"))
{
return 1;
}
if (data_len < PASSKEY_LENGTH)
{
cmd_send_response_u16("rpz:", 0xFFFF);
return 1;
}
if (m_passkey_changed != 0U)
{
// 패스키가 변경된 경우 다시 바꿀 수 없음(FFFF 반환)
cmd_send_response_u16("rpz:", 0xFFFF);
DBG_PRINTF("[CMD] mpz: passkey already changed\r\n");
return 1;
}
// NVS 저장이 모두 성공한 뒤 RAM 값 확정
char new_passkey[PASSKEY_BUF_SIZE];
@@ -164,17 +185,9 @@ int cmd_mpz(const uint8_t *data, uint8_t data_len)
return 1;
}
// 변경 완료 플래그 세트 : 다음 mpz? 명령 차단
err = app_nvs_save_passkey_changed(1U);
if (err)
{
cmd_send_response_u16("rpz:", 0xFFFD);
return 1;
}
memset(m_static_passkey, 0, sizeof(m_static_passkey));
memcpy(m_static_passkey, new_passkey, PASSKEY_LENGTH);
m_passkey_changed = 1U;
cmd_send_response_ascii("rpz:", m_static_passkey, PASSKEY_LENGTH);
return 1;