Add RFCOMM service routine, to send pending configuration requests on RFCOMM channels. Add in RFCOMM channel config flags, to determine which configuration commands have been sent and received.

Add a new RFCOMM_SendChannelSignals() function to transmit a change in V24 terminal handshake lines to the receiving device.

Prevent SABM packets sent to the control DLCI in the RFCOMM layer from creating a new channel entry, as the control DLCI does not have connection data associated with it.

Fix up MSC control packet handling so that received responses can be acknowledged correctly, so that the RFCOMM layer can record when the receiving device has ACKed a sent change in V24 terminal handshake lines.
pull/1469/head
Dean Camera 15 years ago
parent b656540468
commit fbabecee66

@ -58,6 +58,12 @@ int main(void)
for (;;)
{
Bluetooth_Channel_t* RFCOMMChannel = Bluetooth_GetChannelData(CHANNEL_PSM_RFCOMM, CHANNEL_SEARCH_PSM);
/* If an RFCOMM channel is open, service the RFCOMM logical channels */
if (RFCOMMChannel)
RFCOMM_ServiceChannels(RFCOMMChannel);
Bluetooth_Stack_USBTask();
Bluetooth_Host_Task();
USB_USBTask();
@ -215,7 +221,6 @@ void Bluetooth_StackInitialized(void)
Bluetooth_State.LocalBDADDR[2], Bluetooth_State.LocalBDADDR[1], Bluetooth_State.LocalBDADDR[0]);
/* Reinitialize the services placed on top of the Bluetooth stack ready for new connections */
SDP_Initialize();
RFCOMM_Initialize();
}
@ -287,6 +292,7 @@ bool Bluetooth_ChannelConnectionRequest(const uint16_t PSM)
*/
void Bluetooth_PacketReceived(void* Data, uint16_t DataLen, Bluetooth_Channel_t* const Channel)
{
/* Run the correct packet handler based on the received packet's PSM, which indicates the service being carried */
switch (Channel->PSM)
{
case CHANNEL_PSM_SDP:

@ -73,6 +73,32 @@ void RFCOMM_Initialize(void)
RFCOMM_Channels[i].State = RFCOMM_Channel_Closed;
}
void RFCOMM_ServiceChannels(Bluetooth_Channel_t* const BluetoothChannel)
{
for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
{
RFCOMM_Channel_t* RFCOMMChannel = &RFCOMM_Channels[i];
if (RFCOMMChannel->State == RFCOMM_Channel_Configure)
{
/* Check if the local signals have not yet been sent on the current channel */
if (!(RFCOMMChannel->ConfigFlags & RFCOMM_CONFIG_LOCALSIGNALSSENT))
{
/* Indicate that the local signals have been sent, transmit them to the remote device */
RFCOMMChannel->ConfigFlags |= RFCOMM_CONFIG_LOCALSIGNALSSENT;
RFCOMM_SendChannelSignals(RFCOMMChannel, BluetoothChannel);
}
/* If signals have been configured in both directions, progress to the open state */
if ((RFCOMMChannel->ConfigFlags & (RFCOMM_CONFIG_REMOTESIGNALS | RFCOMM_CONFIG_LOCALSIGNALS)) ==
(RFCOMM_CONFIG_REMOTESIGNALS | RFCOMM_CONFIG_LOCALSIGNALS))
{
RFCOMMChannel->State = RFCOMM_Channel_Open;
}
}
}
}
void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
{
const RFCOMM_Header_t* FrameHeader = (const RFCOMM_Header_t*)Data;
@ -103,6 +129,28 @@ void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
}
}
void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t* const RFCOMMChannel, Bluetooth_Channel_t* const BluetoothChannel)
{
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, BluetoothChannel);
}
RFCOMM_Channel_t* RFCOMM_GetChannelData(const uint8_t DLCI)
{
/* Search through the RFCOMM channel list, looking for the specified channel */
@ -155,12 +203,7 @@ void RFCOMM_SendFrame(const uint8_t DLCI, const bool CommandResponse, const uint
/* Set the frame header values to the specified address and frame type */
ResponsePacket.FrameHeader.Control = Control;
ResponsePacket.FrameHeader.Address = (RFCOMM_Address_t)
{
.EA = true,
.CR = CommandResponse,
.DLCI = DLCI,
};
ResponsePacket.FrameHeader.Address = (RFCOMM_Address_t){.DLCI = DLCI, .EA = true, .CR = CommandResponse};
/* Set the lower 7 bits of the packet length */
ResponsePacket.Size[0] = (DataLen << 1);
@ -225,34 +268,46 @@ static void RFCOMM_ProcessSABM(const RFCOMM_Address_t* const FrameAddress, Bluet
BT_RFCOMM_DEBUG(1, "<< SABM Received");
BT_RFCOMM_DEBUG(2, "-- DLCI 0x%02X", FrameAddress->DLCI);
RFCOMM_Channel_t* RFCOMMChannel;
if (FrameAddress->DLCI != RFCOMM_CONTROL_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* CurrRFCOMMChannel = &RFCOMM_Channels[i];
/* If the channel's state is closed, the channel state entry is free */
if (CurrRFCOMMChannel->State == RFCOMM_Channel_Closed)
if (RFCOMM_Channels[i].State == RFCOMM_Channel_Closed)
{
CurrRFCOMMChannel->DLCI = FrameAddress->DLCI;
CurrRFCOMMChannel->State = RFCOMM_Channel_Open;
CurrRFCOMMChannel->Priority = 7 + (CurrRFCOMMChannel->DLCI >> 3) + ((CurrRFCOMMChannel->DLCI >> 3) * 7);
CurrRFCOMMChannel->MTU = 0xFFFF;
CurrRFCOMMChannel->Remote.Signals = 0 | (1 << 0);
CurrRFCOMMChannel->Remote.BreakSignal = 0 | (1 << 0);
CurrRFCOMMChannel->Local.Signals = RFCOMM_SIGNAL_RTC | RFCOMM_SIGNAL_RTR | RFCOMM_SIGNAL_DV | (1 << 0);
CurrRFCOMMChannel->Local.BreakSignal = 0 | (1 << 0);
RFCOMMChannel = &RFCOMM_Channels[i];
RFCOMMChannel->DLCI = FrameAddress->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;
break;
}
}
}
if (RFCOMMChannel || (FrameAddress->DLCI == RFCOMM_CONTROL_DLCI))
{
BT_RFCOMM_DEBUG(1, ">> UA Sent");
/* Free channel found, or request was to the control channel - accept SABM by sending a UA frame */
RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_UA | FRAME_POLL_FINAL), 0, NULL, Channel);
return;
}
}
else
{
BT_RFCOMM_DEBUG(1, ">> DM Sent");
/* No free channel in the multiplexer - decline the SABM by sending a DM frame */
RFCOMM_SendFrame(FrameAddress->DLCI, true, (RFCOMM_Frame_DM | FRAME_POLL_FINAL), 0, NULL, Channel);
}
}
static void RFCOMM_ProcessUA(const RFCOMM_Address_t* const FrameAddress, Bluetooth_Channel_t* const Channel)
{

@ -51,7 +51,7 @@
/* Macros: */
#define BT_RFCOMM_DEBUG(l, s, ...) do { if (RFCOMM_DEBUG_LEVEL >= l) printf_P(PSTR("(RFCOMM) " s "\r\n"), ##__VA_ARGS__); } while (0)
#define RFCOMM_DEBUG_LEVEL 2
#define RFCOMM_DEBUG_LEVEL 0
#define FRAME_POLL_FINAL (1 << 4)
@ -72,11 +72,8 @@
enum RFCOMM_Channel_States_t
{
RFCOMM_Channel_Closed = 0,
RFCOMM_Channel_Create = 1,
RFCOMM_Channel_Creating = 2,
RFCOMM_Channel_Configure = 3,
RFCOMM_Channel_Configuring = 4,
RFCOMM_Channel_Open = 5,
RFCOMM_Channel_Configure = 1,
RFCOMM_Channel_Open = 2,
};
/* Type Defines: */
@ -86,6 +83,7 @@
uint8_t State;
uint8_t Priority;
uint16_t MTU;
uint8_t ConfigFlags;
struct
{
uint8_t Signals;
@ -103,9 +101,13 @@
/* Function Prototypes: */
void RFCOMM_Initialize(void);
void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel);
void RFCOMM_ServiceChannels(Bluetooth_Channel_t* const Channel);
void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const BluetoothChannel);
void RFCOMM_SendChannelSignals(const RFCOMM_Channel_t* const RFCOMMChannel,
Bluetooth_Channel_t* const BluetoothChannel);
RFCOMM_Channel_t* RFCOMM_GetChannelData(const uint8_t DLCI);
uint16_t RFCOMM_GetVariableFieldValue(const uint8_t** BufferPos);
void RFCOMM_SendFrame(const uint8_t DLCI, const bool CommandResponse, const uint8_t Control,
const uint16_t DataLen, const void* Data, Bluetooth_Channel_t* const Channel);

@ -56,7 +56,7 @@ void RFCOMM_ProcessControlCommand(const uint8_t* Command, Bluetooth_Channel_t* c
RFCOMM_ProcessFCDCommand(CommandHeader, CommandData, Channel);
break;
case RFCOMM_Control_ModemStatus:
RFCOMM_ProcessMSCommand(CommandHeader, CommandDataLen, CommandData, Channel);
RFCOMM_ProcessMSCCommand(CommandHeader, CommandDataLen, CommandData, Channel);
break;
case RFCOMM_Control_RemotePortNegotiation:
RFCOMM_ProcessRPNCommand(CommandHeader, CommandData, Channel);
@ -110,12 +110,12 @@ static void RFCOMM_ProcessFCDCommand(const RFCOMM_Command_t* const CommandHeader
BT_RFCOMM_DEBUG(1, "<< FCD Command");
}
static void RFCOMM_ProcessMSCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t CommandDataLen,
static void RFCOMM_ProcessMSCCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t CommandDataLen,
const uint8_t* CommandData, Bluetooth_Channel_t* const Channel)
{
const RFCOMM_MS_Parameters_t* Params = (const RFCOMM_MS_Parameters_t*)CommandData;
const RFCOMM_MSC_Parameters_t* Params = (const RFCOMM_MSC_Parameters_t*)CommandData;
BT_RFCOMM_DEBUG(1, "<< MS Command");
BT_RFCOMM_DEBUG(1, "<< MSC %s", (CommandHeader->CR) ? "Command" : "Response");
BT_RFCOMM_DEBUG(2, "-- DLCI: 0x%02X", Params->Channel.DLCI);
/* Ignore status flags sent to the control channel */
@ -129,31 +129,41 @@ static void RFCOMM_ProcessMSCommand(const RFCOMM_Command_t* const CommandHeader,
if (RFCOMMChannel == NULL)
return;
/* Check if the MSC packet is a command or a response */
if (CommandHeader->CR)
{
/* Save the new channel signals to the channel state structure */
RFCOMMChannel->Remote.Signals = Params->Signals;
RFCOMMChannel->ConfigFlags |= RFCOMM_CONFIG_REMOTESIGNALS;
/* If the command contains the optional break signals field, store the value */
if (CommandDataLen == sizeof(RFCOMM_MS_Parameters_t))
if (CommandDataLen == sizeof(RFCOMM_MSC_Parameters_t))
RFCOMMChannel->Remote.BreakSignal = Params->BreakSignal;
struct
{
RFCOMM_Command_t CommandHeader;
uint8_t Length;
RFCOMM_MS_Parameters_t Params;
RFCOMM_MSC_Parameters_t Params;
} MSResponse;
/* Fill out the MS response data */
MSResponse.CommandHeader = (RFCOMM_Command_t){.Command = RFCOMM_Control_ModemStatus, .EA = true, .CR = false};
MSResponse.Length = (CommandDataLen << 1) | 0x01;
memcpy(&MSResponse.Params, Params, sizeof(RFCOMM_MS_Parameters_t));
memcpy(&MSResponse.Params, Params, sizeof(RFCOMM_MSC_Parameters_t));
BT_RFCOMM_DEBUG(1, ">> MS Response");
BT_RFCOMM_DEBUG(1, ">> MSC Response");
/* Send the PDN response to acknowledge the command */
/* Send the MSC response to acknowledge the command */
RFCOMM_SendFrame(RFCOMM_CONTROL_DLCI, false, RFCOMM_Frame_UIH,
(sizeof(MSResponse) - sizeof(MSResponse.Params) + CommandDataLen), &MSResponse, Channel);
}
else
{
/* Indicate that the remote device has acknowledged the sent signals */
RFCOMMChannel->ConfigFlags |= RFCOMM_CONFIG_LOCALSIGNALS;
}
}
static void RFCOMM_ProcessRPNCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t* CommandData,
Bluetooth_Channel_t* const Channel)
@ -189,7 +199,7 @@ static void RFCOMM_ProcessDPNCommand(const RFCOMM_Command_t* const CommandHeader
for (uint8_t i = 0; i < RFCOMM_MAX_OPEN_CHANNELS; i++)
{
/* If the channel's state is closed, the channel state entry is free */
if (RFCOMMChannel->State == RFCOMM_Channel_Closed)
if (RFCOMM_Channels[i].State == RFCOMM_Channel_Closed)
{
RFCOMMChannel = &RFCOMM_Channels[i];
RFCOMMChannel->DLCI = Params->DLCI;
@ -198,6 +208,7 @@ static void RFCOMM_ProcessDPNCommand(const RFCOMM_Command_t* const CommandHeader
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;
break;
}
}
@ -211,7 +222,7 @@ static void RFCOMM_ProcessDPNCommand(const RFCOMM_Command_t* const CommandHeader
}
/* Save the new channel configuration */
RFCOMMChannel->State = RFCOMM_Channel_Open;
RFCOMMChannel->State = RFCOMM_Channel_Configure;
RFCOMMChannel->Priority = Params->Priority;
RFCOMMChannel->MTU = Params->MaximumFrameSize;

@ -56,6 +56,10 @@
#define RFCOMM_SIGNAL_IC (1 << 6)
#define RFCOMM_SIGNAL_DV (1 << 7)
#define RFCOMM_CONFIG_REMOTESIGNALS (1 << 0)
#define RFCOMM_CONFIG_LOCALSIGNALS (1 << 1)
#define RFCOMM_CONFIG_LOCALSIGNALSSENT (1 << 2)
/* Enums: */
enum RFCOMM_Control_Commands_t
{
@ -107,7 +111,7 @@
RFCOMM_Address_t Channel;
uint8_t Signals;
uint8_t BreakSignal;
} RFCOMM_MS_Parameters_t;
} RFCOMM_MSC_Parameters_t;
/* Function Prototypes: */
void RFCOMM_ProcessControlCommand(const uint8_t* Command, Bluetooth_Channel_t* const Channel);
@ -119,7 +123,7 @@
Bluetooth_Channel_t* const Channel);
static void RFCOMM_ProcessFCDCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t* CommandData,
Bluetooth_Channel_t* const Channel);
static void RFCOMM_ProcessMSCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t CommandDataLen,
static void RFCOMM_ProcessMSCCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t CommandDataLen,
const uint8_t* CommandData, Bluetooth_Channel_t* const Channel);
static void RFCOMM_ProcessRPNCommand(const RFCOMM_Command_t* const CommandHeader, const uint8_t* CommandData,
Bluetooth_Channel_t* const Channel);

@ -52,12 +52,6 @@ const ServiceAttributeTable_t* SDP_Services_Table[] PROGMEM =
/** Base UUID value common to all standardized Bluetooth services */
const UUID_t BaseUUID PROGMEM = {0x00000000, BASE_80BIT_UUID};
/** Initializes the SDP service, ready for new connections from a SDP client. */
void SDP_Initialize(void)
{
/* Not currently used */
}
/** Main Service Discovery Protocol packet processing routine. This function processes incomming SDP packets from
* a connected Bluetooth device, and sends back appropriate responses to allow other devices to determine the
* services the local device exposes.

@ -203,7 +203,6 @@
}
/* Function Prototypes: */
void SDP_Initialize(void);
void SDP_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel);
#if defined(INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C)

Loading…
Cancel
Save