코드 정리
This commit is contained in:
+22
-79
@@ -1,13 +1,13 @@
|
||||
/*******************************************************************************
|
||||
* @file ble_service.c
|
||||
* @brief BLE NUS service module (Zephyr port)
|
||||
* @brief BLE NUS service module
|
||||
*
|
||||
* Original VesiScan-Basic BLE implementation ported to Zephyr/NCS:
|
||||
* - NUS (Nordic UART Service) for data exchange
|
||||
* - Advertising: 40ms interval, 10-min timeout
|
||||
* - Connection: 15ms interval, 0 latency, 10s supervision timeout
|
||||
* - TX power +8 dBm, 2M PHY preferred
|
||||
* - Dev mode: no security / Production mode: bonding + passkey (TODO)
|
||||
* - Dev mode: no security / Production mode: bonding + passkey
|
||||
******************************************************************************/
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
@@ -45,18 +45,8 @@ static uint32_t pairing_passkey = BT_PASSKEY_RAND;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NUS 전송은 "보냈다" 호출만 한다고 바로 끝나는 게 아니다.
|
||||
* 내부 TX 버퍼에 들어간 뒤 실제로 무선으로 나가고,
|
||||
* Zephyr가 sent 콜백을 줄 때 비로소 한 건이 끝났다고 볼 수 있다.
|
||||
*
|
||||
* 그래서 아래 2개를 같이 쓴다.
|
||||
* - mutex: 여러 곳에서 동시에 NUS 전송을 시작하지 못하게 막음
|
||||
* - sem : "직전 전송이 정말 끝났는지" 기다리는 신호
|
||||
*
|
||||
* mbb?처럼 큰 패킷을 여러 개 연속으로 보내는 경우 이 보호가 없으면
|
||||
* - 중간에 -ENOMEM이 뜨거나
|
||||
* - 몇 개는 나가고 몇 개는 실패하거나
|
||||
* - 앱 쪽에서 응답이 꼬여 보일 수 있다.
|
||||
*/
|
||||
static struct k_mutex nus_tx_lock;
|
||||
static struct k_sem nus_tx_done_sem;
|
||||
@@ -65,27 +55,20 @@ static struct k_sem nus_tx_done_sem;
|
||||
static struct k_work adv_restart_work;
|
||||
static struct k_work_delayable adv_timeout_work;
|
||||
static struct k_work_delayable conn_param_update_work;
|
||||
static const bt_addr_le_t fixed_identity_addr = {
|
||||
.type = BT_ADDR_LE_RANDOM,
|
||||
.a = {
|
||||
.val = { 0xF1, 0x8E, 0x81, 0xFA, 0x87, 0xC5 },
|
||||
},
|
||||
};
|
||||
|
||||
static const char *ble_addr_type_str(uint8_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BT_ADDR_LE_PUBLIC:
|
||||
return "public";
|
||||
case BT_ADDR_LE_RANDOM:
|
||||
return "random";
|
||||
case BT_ADDR_LE_PUBLIC_ID:
|
||||
return "public-id";
|
||||
case BT_ADDR_LE_RANDOM_ID:
|
||||
return "random-id";
|
||||
default:
|
||||
return "unknown";
|
||||
case BT_ADDR_LE_PUBLIC:
|
||||
return "public";
|
||||
case BT_ADDR_LE_RANDOM:
|
||||
return "random";
|
||||
case BT_ADDR_LE_PUBLIC_ID:
|
||||
return "public-id";
|
||||
case BT_ADDR_LE_RANDOM_ID:
|
||||
return "random-id";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,39 +81,12 @@ static void ble_log_local_identity(void)
|
||||
bt_id_get(&addr, &count);
|
||||
if (count == 0U)
|
||||
{
|
||||
DBG_ERR("[BLE] No local identity address\r\n");
|
||||
DBG_ERR("[BLE] No local identity (MAC address) configured\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
|
||||
DBG_CORE("[BLE] Local identity: %s (%s)\r\n",
|
||||
addr_str,
|
||||
ble_addr_type_str(addr.type));
|
||||
}
|
||||
|
||||
static int ble_configure_fixed_identity(void)
|
||||
{
|
||||
bt_addr_le_t addr = fixed_identity_addr;
|
||||
char addr_str[BT_ADDR_LE_STR_LEN];
|
||||
int id;
|
||||
|
||||
bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
|
||||
DBG_CORE("[BLE] Request fixed identity: %s\r\n", addr_str);
|
||||
|
||||
id = bt_id_create(&addr, NULL);
|
||||
if (id < 0)
|
||||
{
|
||||
DBG_ERR("[BLE] bt_id_create failed (err %d)\r\n", id);
|
||||
return id;
|
||||
}
|
||||
|
||||
if (id != BT_ID_DEFAULT)
|
||||
{
|
||||
DBG_ERR("[BLE] Unexpected identity slot %d\r\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
DBG_CORE("[BLE] Local identity (MAC address): %s\r\n", addr_str);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||
@@ -551,9 +507,9 @@ static void nus_received(struct bt_conn *conn, const uint8_t *data, uint16_t len
|
||||
static void nus_sent(struct bt_conn *conn)
|
||||
{
|
||||
ARG_UNUSED(conn);
|
||||
/* 이 시점이 "직전 NUS 패킷 전송이 끝났다"는 완료 신호다. */
|
||||
/* 직전 NUS 패킷 전송 완료 */
|
||||
k_sem_give(&nus_tx_done_sem);
|
||||
DBG_CORE("[NUS TX] complete\r\n");
|
||||
//DBG_CORE("[NUS TX] complete\r\n");
|
||||
}
|
||||
|
||||
static struct bt_nus_cb nus_cb =
|
||||
@@ -577,12 +533,6 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
|
||||
k_work_init_delayable(&adv_timeout_work, adv_timeout_handler);
|
||||
k_work_init_delayable(&conn_param_update_work, conn_param_update_handler);
|
||||
|
||||
err = ble_configure_fixed_identity();
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable BLE stack */
|
||||
err = bt_enable(NULL);
|
||||
if (err)
|
||||
@@ -731,18 +681,14 @@ int ble_data_send(const uint8_t *data, uint16_t len)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NUS는 한 번에 한 패킷씩 질서 있게 보내는 편이 안전하다.
|
||||
* 특히 mbb?는 rbb + reb x6 + raa처럼 여러 응답을 연속 전송하므로
|
||||
* 먼저 들어온 전송이 끝나기 전 다음 전송이 겹치지 않게 잠근다.
|
||||
*/
|
||||
/* 먼저 들어온 전송이 끝나기 전 다음 전송이 겹치지 않게 잠금 (NUS는 한 번에 한 패킷씩 보내는 것이 안전) */
|
||||
k_mutex_lock(&nus_tx_lock, K_FOREVER);
|
||||
|
||||
/* 혹시 남아 있는 완료 신호가 있으면 비워서 "이번 전송 전용" 상태로 만든다. */
|
||||
/* 혹시 남아 있는 완료 신호가 있으면 비우고 이번 전송 전용 상태로 만듦 */
|
||||
while (k_sem_take(&nus_tx_done_sem, K_NO_WAIT) == 0) {
|
||||
}
|
||||
|
||||
DBG_CORE("[NUS TX] send len=%u\r\n", len);
|
||||
//DBG_CORE("[NUS TX] send len=%u\r\n", len);
|
||||
for (int retry = 0; ; retry++)
|
||||
{
|
||||
err = bt_nus_send(current_conn, data, len);
|
||||
@@ -751,8 +697,8 @@ int ble_data_send(const uint8_t *data, uint16_t len)
|
||||
}
|
||||
|
||||
/*
|
||||
* -ENOMEM은 지금 당장 보낼 자리(TX 버퍼)가 없다는 뜻이다.
|
||||
* 바로 포기하지 않고 짧게 쉬었다가 다시 시도한다.
|
||||
* -ENOMEM : BLE TX 버퍼가 가득참
|
||||
* 바로 포기하지 않고 짧게 쉬었다가 다시 시도
|
||||
*/
|
||||
DBG_ERR("[NUS TX] busy, retry=%d\r\n", retry + 1);
|
||||
k_msleep(5);
|
||||
@@ -765,10 +711,7 @@ int ble_data_send(const uint8_t *data, uint16_t len)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* bt_nus_send()가 성공했다고 해서 공중으로 다 나간 것은 아니다.
|
||||
* sent 콜백이 올 때까지 조금 기다려서 "다음 패킷을 보내도 되는 시점"을 맞춘다.
|
||||
*/
|
||||
/* bt_nus_send() 성공 후 sent 콜백이 올 때까지 기다림 (다음 패킷을 보내도 되는 시점) */
|
||||
err = k_sem_take(&nus_tx_done_sem, K_MSEC(1000));
|
||||
if (err)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user