+/** Sends an RFCOMM notification to the remote device that the local terminal control signals (located in the
+ * "Local" structure of the RFCOMM channel) have changed, pushing the new signals to the remote device.
+ *
+ * \param[in] RFCOMMChannel RFCOMM logical channel whose local terminal signals have changed
+ * \param[in] ACLChannel ACL channel which has been opened to carry RFCOMM traffic between devices
+ */
+void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t* const RFCOMMChannel,
+ Bluetooth_Channel_t* const ACLChannel)
+{
+ BT_RFCOMM_DEBUG(1, ">> MSC Command");
+ BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
+
+ struct
+ {
+ RFCOMM_Command_t CommandHeader;
+ uint8_t Length;
+ RFCOMM_MSC_Parameters_t Params;
+ } MSCommand;
+
+ MSCommand.CommandHeader = (RFCOMM_Command_t){.Command = RFCOMM_Control_ModemStatus, .EA = true, .CR = true};
+ MSCommand.Length = (sizeof(MSCommand.Params) << 1) | 0x01;
+ MSCommand.Params.Channel = (RFCOMM_Address_t){.DLCI = RFCOMMChannel->DLCI, .EA = true, .CR = true};
+ MSCommand.Params.Signals = RFCOMMChannel->Local.Signals;
+ MSCommand.Params.BreakSignal = RFCOMMChannel->Local.BreakSignal;
+
+ /* Send the MSC command to the remote device */
+ RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI, true, RFCOMM_Frame_UIH, sizeof(MSCommand), &MSCommand, ACLChannel);
+}
+
+/** Sends new data through an open logical RFCOMM channel. This should be used to transmit data through a
+ * RFCOMM channel once it has been opened.
+ *
+ * \param[in] DataLen Length of the RFCOMM data to send, in bytes
+ * \param[in] Data Pointer to a buffer where the data to send is located
+ * \param[in] RFCOMMChannel RFCOMM logical channel which is to be transmitted to
+ * \param[in] ACLChannel ACL channel which has been opened to carry RFCOMM traffic between devices
+ */
+void RFCOMM_SendData(const uint16_t DataLen,
+ const uint8_t* Data,
+ const RFCOMM_Channel_t* const RFCOMMChannel,
+ Bluetooth_Channel_t* const ACLChannel)
+{
+ if (RFCOMMChannel->State != RFCOMM_Channel_Open)
+ return;
+
+ BT_RFCOMM_DEBUG(1, ">> UIH Frame");
+ BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", RFCOMMChannel->DLCI);
+
+ /* Send the MSC command to the remote device */
+ RFCOMM_SendFrame(RFCOMMChannel->DLCI, false, RFCOMM_Frame_UIH, DataLen, Data, ACLChannel);
+}
+
+RFCOMM_Channel_t* RFCOMM_GetFreeChannelEntry(const uint8_t DLCI)
+{
+ /* Find a free entry in the RFCOMM channel multiplexer state array */
+ for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
+ {
+ RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
+
+ /* If the channel's state is closed, the channel state entry is free */
+ if (RFCOMMChannel->State == RFCOMM_Channel_Closed)
+ {
+ RFCOMMChannel->DLCI = DLCI;
+ RFCOMMChannel->State = RFCOMM_Channel_Configure;
+ RFCOMMChannel->Priority = 7 + (RFCOMMChannel->DLCI & 0xF8);
+ RFCOMMChannel->MTU = 0xFFFF;
+ RFCOMMChannel->Remote.Signals = 0 | (1 << 0);
+ RFCOMMChannel->Remote.BreakSignal = 0 | (1 << 0);
+ RFCOMMChannel->Local.Signals = RFCOMM_SIGNAL_RTC | RFCOMM_SIGNAL_RTR | RFCOMM_SIGNAL_DV | (1 << 0);
+ RFCOMMChannel->Local.BreakSignal = 0 | (1 << 0);
+ RFCOMMChannel->ConfigFlags = 0;
+
+ return RFCOMMChannel;
+ }
+ }
+
+ return NULL;
+}
+