diff --git a/src/dmr/Control.cpp b/src/dmr/Control.cpp index c61c31cb..13e6b148 100644 --- a/src/dmr/Control.cpp +++ b/src/dmr/Control.cpp @@ -420,7 +420,8 @@ Slot* Control::getTSCCSlot() const /// DMR slot number. /// /// -void Control::tsccActivateSlot(uint32_t slotNo, uint32_t dstId, bool group) +/// +void Control::tsccActivateSlot(uint32_t slotNo, uint32_t dstId, bool group, bool voice) { if (m_verbose) { LogMessage(LOG_DMR, "DMR Slot %u, payload activation, group = %u, dstId = %u", @@ -436,11 +437,11 @@ void Control::tsccActivateSlot(uint32_t slotNo, uint32_t dstId, bool group) switch (slotNo) { case 1U: m_tsccPayloadActive = true; - m_slot1->setTSCCActivated(dstId, group); + m_slot1->setTSCCActivated(dstId, group, voice); break; case 2U: m_tsccPayloadActive = true; - m_slot2->setTSCCActivated(dstId, group); + m_slot2->setTSCCActivated(dstId, group, voice); break; default: LogError(LOG_DMR, "DMR, invalid slot, TSCC payload activation, slotNo = %u", slotNo); diff --git a/src/dmr/Control.h b/src/dmr/Control.h index 83bef7f1..ce6a1674 100644 --- a/src/dmr/Control.h +++ b/src/dmr/Control.h @@ -100,7 +100,7 @@ namespace dmr /// Helper to return the slot carrying the TSCC. Slot* getTSCCSlot() const; /// Helper to payload activate the slot carrying granted payload traffic. - void tsccActivateSlot(uint32_t slotNo, uint32_t dstId, bool group); + void tsccActivateSlot(uint32_t slotNo, uint32_t dstId, bool group, bool voice); /// Helper to clear an activated payload slot. void tsccClearActivatedSlot(uint32_t slotNo); diff --git a/src/dmr/Slot.cpp b/src/dmr/Slot.cpp index ef0c72b2..464a7248 100644 --- a/src/dmr/Slot.cpp +++ b/src/dmr/Slot.cpp @@ -158,6 +158,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_dedicatedTSCC(false), m_tsccPayloadDstId(0U), m_tsccPayloadGroup(false), + m_tsccPayloadVoice(true), m_verbose(verbose), m_debug(debug) { @@ -470,7 +471,7 @@ void Slot::clock() if (m_rfState == RS_RF_LISTENING && m_netState == RS_NET_IDLE) { if (m_tsccPayloadDstId > 0U) { if ((m_dmr->m_tsccCnt % 2) > 0) { - setShortLC(m_slotNo, m_tsccPayloadDstId, m_tsccPayloadGroup ? FLCO_GROUP : FLCO_PRIVATE, false); + setShortLC(m_slotNo, m_tsccPayloadDstId, m_tsccPayloadGroup ? FLCO_GROUP : FLCO_PRIVATE, m_tsccPayloadVoice); } } } diff --git a/src/dmr/Slot.h b/src/dmr/Slot.h index 31e7af74..44298283 100644 --- a/src/dmr/Slot.h +++ b/src/dmr/Slot.h @@ -106,7 +106,7 @@ namespace dmr /// Helper to enable and configure TSCC support for this slot. void setTSCC(bool enable, bool dedicated); /// Sets a flag indicating whether the slot is a TSCC payload slot. - void setTSCCActivated(uint32_t dstId, bool group) { m_tsccPayloadDstId = dstId; m_tsccPayloadGroup = group; } + void setTSCCActivated(uint32_t dstId, bool group, bool voice) { m_tsccPayloadDstId = dstId; m_tsccPayloadGroup = group; m_tsccPayloadVoice = voice; } /// Sets a flag indicating whether the DMR control channel can send permit-tg to voice channels. void setControlPermitTG(bool controlPermitTG) { m_controlPermitTG = controlPermitTG; } /// Helper to set the voice error silence threshold. @@ -194,6 +194,7 @@ namespace dmr uint32_t m_tsccPayloadDstId; bool m_tsccPayloadGroup; + bool m_tsccPayloadVoice; bool m_controlPermitTG; @@ -264,7 +265,7 @@ namespace dmr void writeRF_ControlData(uint16_t frameCnt, uint8_t n); /// Clears the flag indicating whether the slot is a TSCC payload slot. - void clearTSCCActivated() { m_tsccPayloadDstId = 0U; m_tsccPayloadGroup = false; } + void clearTSCCActivated() { m_tsccPayloadDstId = 0U; m_tsccPayloadGroup = false; m_tsccPayloadVoice = true; } /// Helper to set the DMR short LC. static void setShortLC(uint32_t slotNo, uint32_t id, uint8_t flco = FLCO_GROUP, bool voice = true); diff --git a/src/dmr/packet/ControlSignaling.cpp b/src/dmr/packet/ControlSignaling.cpp index e29994a2..1baf9da0 100644 --- a/src/dmr/packet/ControlSignaling.cpp +++ b/src/dmr/packet/ControlSignaling.cpp @@ -849,16 +849,18 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ req["dstId"].set(dstId); req["slot"].set(slot); req["group"].set(grp); + bool voice = true; + req["voice"].set(voice); RESTClient::send(voiceChData.address(), voiceChData.port(), voiceChData.password(), - HTTP_PUT, PUT_DMR_TSCC_PAYLOAD_ACT, req, m_tscc->m_debug); + HTTP_PUT, PUT_DMR_TSCC_PAYLOAD_ACT, req, m_tscc->m_debug); } else { ::LogError(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), failed to activate payload channel, chNo = %u, slot = %u", m_tscc->m_slotNo, chNo, slot); } } else { - m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp); + m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp, true); } // callback RCON to permit-tg on the specified voice channel @@ -911,6 +913,8 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ req["dstId"].set(dstId); req["slot"].set(slot); req["group"].set(grp); + bool voice = true; + req["voice"].set(voice); RESTClient::send(voiceChData.address(), voiceChData.port(), voiceChData.password(), HTTP_PUT, PUT_DMR_TSCC_PAYLOAD_ACT, req, m_tscc->m_debug); @@ -920,7 +924,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ } } else { - m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp); + m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp, true); } // callback RCON to permit-tg on the specified voice channel @@ -1082,6 +1086,8 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u req["dstId"].set(dstId); req["slot"].set(slot); req["group"].set(grp); + bool voice = false; + req["voice"].set(voice); RESTClient::send(voiceChData.address(), voiceChData.port(), voiceChData.password(), HTTP_PUT, PUT_DMR_TSCC_PAYLOAD_ACT, req, m_tscc->m_debug); @@ -1091,7 +1097,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u } } else { - m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp); + m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp, false); } std::unique_ptr csbk = new_unique(CSBK_TD_GRANT); @@ -1124,6 +1130,8 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u req["dstId"].set(dstId); req["slot"].set(slot); req["group"].set(grp); + bool voice = false; + req["voice"].set(voice); RESTClient::send(voiceChData.address(), voiceChData.port(), voiceChData.password(), HTTP_PUT, PUT_DMR_TSCC_PAYLOAD_ACT, req, m_tscc->m_debug); @@ -1133,7 +1141,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u } } else { - m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp); + m_slot->m_dmr->tsccActivateSlot(slot, dstId, grp, false); } std::unique_ptr csbk = new_unique(CSBK_PD_GRANT); diff --git a/src/network/RESTAPI.cpp b/src/network/RESTAPI.cpp index fe563561..0f80a748 100644 --- a/src/network/RESTAPI.cpp +++ b/src/network/RESTAPI.cpp @@ -1438,15 +1438,22 @@ void RESTAPI::restAPI_PutTSCCPayloadActivate(const HTTPPayload& request, HTTPPay return; } + // validate voice flag is a boolean within the JSON blob + if (!req["voice"].is()) { + errorPayload(reply, "voice flag was not valid"); + return; + } + uint32_t dstId = req["dstId"].get(); bool group = req["group"].get(); + bool voice = req["voice"].get(); if (dstId == 0U) { errorPayload(reply, "destination ID was not valid"); return; } - m_dmr->tsccActivateSlot(slot, dstId, group); + m_dmr->tsccActivateSlot(slot, dstId, group, voice); } #else errorPayload(reply, "DMR operations are unavailable", HTTPPayload::SERVICE_UNAVAILABLE);