에러 커맨드 추가
- rxx: (Unknown command) - 수신 TAG가 명령 테이블에 없는 경우 - rxd: (Disabled command) - 수신 TAG가 테이블에 있지만 enabled=false로 비활성화된 경우 - rxn: (NULL handler) - 엔트리는 매칭됐지만 함수 포인터가 NULL인 경우(펌웨어 버그 방어) - rxc: (CRC fail) - CRC16 검증 실패 - rxs: (Too short) - 패킷이 너무 짧은 경우(CRC 활성 시 7바이트 미만, 비활성 시 4바이트 미만)
This commit is contained in:
@@ -278,6 +278,20 @@ static bool dr_crc16_check_packet(const uint8_t *packet, uint32_t packet_len)
|
||||
return dr_crc16_check(packet, data_len, expected_crc);
|
||||
}
|
||||
|
||||
/* ---- 에러 응답 헬퍼 ----
|
||||
* 패킷: [err_tag 4B] [cmd_tag 에코 4B] = 8바이트 = 4워드
|
||||
* CRC16은 tx_bin 레이어에서 자동 부가
|
||||
*/
|
||||
static void dr_send_error(const char *err_tag, const char *cmd_tag)
|
||||
{
|
||||
if (g_plat.tx_bin) {
|
||||
uint8_t err_buf[8];
|
||||
memcpy(&err_buf[0], err_tag, 4);
|
||||
memcpy(&err_buf[4], cmd_tag, 4);
|
||||
g_plat.tx_bin(err_buf, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 수신 버퍼 → ParsedCmd 구조체 변환 ---- */
|
||||
|
||||
/* 수신된 원시 바이트 버퍼를 파싱하여 TAG와 데이터를 분리
|
||||
@@ -289,43 +303,57 @@ static bool dr_crc16_check_packet(const uint8_t *packet, uint32_t packet_len)
|
||||
*/
|
||||
static bool dr_parse_cmd(const uint8_t *buffer, uint8_t length, ParsedCmd *out)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t data_len;
|
||||
|
||||
/* TAG 4바이트조차 수신되지 않음 → rxs: + "????" (TAG 특정 불가) */
|
||||
if (length < 4) {
|
||||
return false; /* TAG 4바이트조차 수신되지 않음 */
|
||||
dr_send_error("rxs:", "????");
|
||||
if (g_plat.log && g_log_enable) {
|
||||
g_plat.log("[parser] too short (%u bytes) -> rxs:\r\n", length);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TAG 먼저 추출 (에러 응답 에코에 사용) */
|
||||
dr_copy_tag(buffer, out->tag);
|
||||
|
||||
/* CRC 검증이 활성화된 경우 패킷 무결성 확인 */
|
||||
if (g_plat.crc_check)
|
||||
{
|
||||
if (!dr_crc16_check_packet(buffer, length))
|
||||
{
|
||||
if (length < 7) {
|
||||
dr_send_error("rxs:", out->tag);
|
||||
if (g_plat.log && g_log_enable) {
|
||||
g_plat.log("CRC check FAILED!\n");
|
||||
g_plat.log("[parser] CRC enabled but too short (%u) -> rxs:\r\n", length);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* CRC 검증 성공 → CRC 2바이트를 제외한 실제 데이터 길이로 조정 */
|
||||
length = (uint8_t)(length - 2);
|
||||
if (!dr_crc16_check_packet(buffer, length))
|
||||
{
|
||||
dr_send_error("rxc:", out->tag);
|
||||
if (g_plat.log && g_log_enable) {
|
||||
g_plat.log("[parser] CRC mismatch '%s' -> rxc:\r\n", out->tag);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
data_len = (uint8_t)(length - 4 - 2); /* TAG(4) + CRC(2) 제외 */
|
||||
}
|
||||
|
||||
/* TAG 4바이트 복사 */
|
||||
dr_copy_tag(buffer, out->tag);
|
||||
|
||||
/* TAG 이후 데이터 길이 계산 (최대 DR_MAX_DATA까지) */
|
||||
out->data_len = (length > 4) ? (uint8_t)(length - 4) : 0;
|
||||
if (out->data_len > DR_MAX_DATA)
|
||||
else
|
||||
{
|
||||
out->data_len = DR_MAX_DATA;
|
||||
data_len = (uint8_t)(length - 4); /* TAG(4) 제외 */
|
||||
}
|
||||
|
||||
/* TAG 뒤의 데이터 바이트를 ParsedCmd.data[]에 복사 */
|
||||
for (i = 0; i < out->data_len; i++)
|
||||
{
|
||||
out->data[i] = buffer[4 + i];
|
||||
/* 최대 길이 클램프 */
|
||||
if (data_len > DR_MAX_DATA) {
|
||||
data_len = DR_MAX_DATA;
|
||||
}
|
||||
|
||||
if (data_len > 0) {
|
||||
memcpy(out->data, buffer + 4, data_len);
|
||||
}
|
||||
out->data_len = data_len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -488,10 +516,20 @@ static int dr_cmd_dispatch(const ParsedCmd *cmd)
|
||||
for (i = 0; i < g_cmd_count; i++) {
|
||||
if (dr_tag_eq(tag_lower, g_cmd_table[i].tag)) {
|
||||
|
||||
/* 비활성화된 명령이면 실행하지 않음 */
|
||||
/* 비활성화된 명령 → rxd: 응답 */
|
||||
if (!g_cmd_table[i].enabled) {
|
||||
dr_send_error("rxd:", cmd->tag);
|
||||
if (g_plat.log && g_log_enable) {
|
||||
g_plat.log("Command '%s' disabled\n", cmd->tag);
|
||||
g_plat.log("Command '%s' disabled -> rxd:\n", cmd->tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NULL 핸들러 가드 → rxn: 응답 */
|
||||
if (g_cmd_table[i].handler == NULL) {
|
||||
dr_send_error("rxn:", cmd->tag);
|
||||
if (g_plat.log) {
|
||||
g_plat.log("[parser] NULL handler for '%s' -> rxn:\n", cmd->tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -501,9 +539,10 @@ static int dr_cmd_dispatch(const ParsedCmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/* 테이블에 없는 TAG 수신 시 */
|
||||
/* 테이블에 없는 TAG → rxx: 응답 */
|
||||
dr_send_error("rxx:", cmd->tag);
|
||||
if (g_plat.log && g_log_enable) {
|
||||
g_plat.log("Unknown TAG '%s'\n", cmd->tag);
|
||||
g_plat.log("Unknown TAG '%s' -> rxx:\n", cmd->tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -523,16 +562,10 @@ int dr_cmd_parser(const uint8_t *buf, uint8_t len)
|
||||
{
|
||||
ParsedCmd cmd;
|
||||
|
||||
/* 패킷 파싱 (CRC 검증 포함) */
|
||||
/* 패킷 파싱 (CRC 검증 포함) - 에러 응답은 dr_parse_cmd 내부에서 전송 */
|
||||
if (!dr_parse_cmd(buf, len, &cmd)) {
|
||||
if (g_plat.log) g_plat.log("[PARSER] PARSE FAIL\r\n");
|
||||
|
||||
/* CRC 실패 시 "crc!" 에러 응답을 BLE로 전송 (65530 = 에러 코드) */
|
||||
if (g_plat.crc_check && g_plat.tx_bin) {
|
||||
single_format_data(ble_bin_buffer, "crc!", 65530);
|
||||
dr_binary_tx_safe(ble_bin_buffer, 3);
|
||||
}
|
||||
return -1; /* CRC/파싱 실패 → 음수 반환으로 레거시 파서에 위임 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 수신 명령어 종류 확인용 로그 */
|
||||
|
||||
Reference in New Issue
Block a user