diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothACLPackets.c b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothACLPackets.c
index 03d0f2acae3074f9b08cf0c1e7ca0721ed91e9e1..df8dfc5c1d8ff864b09d21f65cbd3be5e950a932 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothACLPackets.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothACLPackets.c
@@ -28,6 +28,13 @@
   this software.
 */
 
+/** \file
+ *
+ *  Bluetooth L2CAP layer management code. This module managed the creation,
+ *  configuration and teardown of L2CAP channels, and manages packet reception
+ *  and sending to and from other Bluetooth devices.
+ */
+
 /*
 	TODO: Make SendPacket respect receiver's MTU
 	TODO: Make ReceivePacket stitch together MTU fragments (?)
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothHCICommands.c b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothHCICommands.c
index 57b74e089b59fd7da2b0caa061f1f4961476e059..d718752127b22b3cdf8849b6790d9e343ba81955 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothHCICommands.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothHCICommands.c
@@ -28,6 +28,15 @@
   this software.
 */
 
+/** \file
+ *
+ *  Bluetooth HCI layer management code. This module manages the overall
+ *  Bluetooth stack connection state to and from other devices, processes
+ *  received events from the Bluetooth controller, and issues commands to
+ *  modify the controller's configuration, such as the broadcast name of the
+ *  device.
+ */
+
 /*
 	TODO: Add local to remote device connections
  */
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothStack.c b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothStack.c
index d78a9efa19fbcdf1b65bc4f39ba7fddc4ac22b55..1a667987b3557293edddd1f74427c9cf65b6d80a 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothStack.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/BluetoothStack.c
@@ -28,6 +28,12 @@
   this software.
 */
 
+/** \file
+ *
+ *  Main module for the Bluetooth stack. This module contains the overall Bluetooth
+ *  stack state variables and the main Bluetooth stack management functions.
+ */
+
 #include "BluetoothStack.h"
 
 /** Bluetooth device connection information structure. Once connected to a remote device, this structure tracks the
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.c b/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.c
index a441ae1564c1e82151923702e7b5191bbb736005..510160629d154214de978f1bb938186df17e26b5 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.c
@@ -28,6 +28,13 @@
   this software.
 */
 
+/** \file
+ *
+ *  RFCOMM layer module. This module manages the RFCOMM layer of the
+ *  stack, providing virtual serial port channels on top of the lower
+ *  L2CAP layer.
+ */
+
 #define  INCLUDE_FROM_RFCOMM_C
 #include "RFCOMM.h"
 
@@ -62,10 +69,10 @@ void RFCOMM_Initialize(void)
 
 void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
 {
-	RFCOMM_Header_t* FrameHeader = (RFCOMM_Header_t*)Data;
+	const RFCOMM_Header_t* FrameHeader = (const RFCOMM_Header_t*)Data;
 	
 	/* Decode the RFCOMM frame type from the header */
-	switch (FrameHeader->FrameType & ~FRAME_POLL_FINAL)
+	switch (FrameHeader->Control & ~FRAME_POLL_FINAL)
 	{
 		case RFCOMM_Frame_SABM:
 			RFCOMM_ProcessSABM(FrameHeader, Channel);
@@ -82,54 +89,94 @@ void RFCOMM_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
 		case RFCOMM_Frame_UIH:
 			RFCOMM_ProcessUIH(FrameHeader, Channel);
 			break;
+		default:
+			BT_RFCOMM_DEBUG(1, "<< Unknown Frame Type");
+			break;
 	}
 }
 
 static void RFCOMM_ProcessSABM(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel)
 {
-	uint8_t* CurrBufferPos = ((uint8_t*)FrameHeader + sizeof(RFCOMM_Header_t));
-	uint16_t DataLen       = RFCOMM_GetFrameDataLength(&CurrBufferPos);
-
 	BT_RFCOMM_DEBUG(1, "<< SABM Received");
-	BT_RFCOMM_DEBUG(2, "-- Data Length 0x%04X", DataLen);
+	BT_RFCOMM_DEBUG(2, "-- Address 0x%02X", FrameHeader->Address);
+	
+	// TODO: Reset channel send/receive state here
+	
+	struct
+	{
+		RFCOMM_Header_t FrameHeader;
+		uint8_t         FrameLength;
+		uint8_t         FCS;
+	} ResponsePacket;
+	
+	/* Copy over the same frame header as the sent packet to copy the logical RFCOMM channel address */
+	ResponsePacket.FrameHeader.Address              = FrameHeader->Address;
+	
+	/* Set the frame type to an Unnumbered Acknowledgement to acknowledge the SABM request */
+	ResponsePacket.FrameHeader.Control = RFCOMM_Frame_UA;
+	
+	/* Set the length to 0 (LSB indicates end of 8-bit length field) */
+	ResponsePacket.FrameLength = 0x01;
+	
+	/* Calculate the frame checksum from all fields except the FCS field itself */
+	ResponsePacket.FCS = RFCOMM_GetFCSValue(&ResponsePacket, sizeof(ResponsePacket) - sizeof(ResponsePacket.FCS));
+	
+	BT_RFCOMM_DEBUG(1, ">> UA Sent");
 
-	for (uint16_t i = 0; i < DataLen; i++)
-	  printf("0x%02X ", CurrBufferPos[i]);
-	printf("\r\n");
+	/* Send the completed response packet to the sender */
+	Bluetooth_SendPacket(&ResponsePacket, sizeof(ResponsePacket), Channel);
 }
 
 static void RFCOMM_ProcessUA(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel)
 {
+	const uint8_t* CurrBufferPos = ((const uint8_t*)FrameHeader + sizeof(RFCOMM_Header_t));
+
 	BT_RFCOMM_DEBUG(1, "<< UA Received");
+	BT_RFCOMM_DEBUG(2, "-- Address 0x%02X", FrameHeader->Address);
 }
 
 static void RFCOMM_ProcessDM(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel)
 {
+	const uint8_t* CurrBufferPos = ((const uint8_t*)FrameHeader + sizeof(RFCOMM_Header_t));
+
 	BT_RFCOMM_DEBUG(1, "<< DM Received");
+	BT_RFCOMM_DEBUG(2, "-- Address 0x%02X", FrameHeader->Address);
 }
 
 static void RFCOMM_ProcessDISC(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel)
 {
+	const uint8_t* CurrBufferPos = ((const uint8_t*)FrameHeader + sizeof(RFCOMM_Header_t));
+
 	BT_RFCOMM_DEBUG(1, "<< DISC Received");
+	BT_RFCOMM_DEBUG(2, "-- Address 0x%02X", FrameHeader->Address);
 }
 
 static void RFCOMM_ProcessUIH(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel)
 {
+	const uint8_t* CurrBufferPos = ((const uint8_t*)FrameHeader + sizeof(RFCOMM_Header_t));
+
 	BT_RFCOMM_DEBUG(1, "<< UIH Received");
+	BT_RFCOMM_DEBUG(2, "-- Address 0x%02X", FrameHeader->Address);
 }
 
-static uint16_t RFCOMM_GetFrameDataLength(void** BufferPos)
+static uint8_t RFCOMM_GetFCSValue(const void* FrameStart, uint16_t Length)
 {
-	uint8_t FirstOctet = *((uint8_t*)*BufferPos);
-	(*BufferPos)++;
+	const uint8_t* CurrPos = FrameStart;
+	uint8_t        FCS     = 0xFF;
+	
+	while (Length--)
+	  FCS = pgm_read_byte(CRC8_Table[FCS ^ *(CurrPos++)]);
 
+	return ~FCS;
+}
+
+static uint16_t RFCOMM_GetFrameDataLength(const uint8_t** BufferPos)
+{
+	uint8_t FirstOctet  = *((*BufferPos)++);
 	uint8_t SecondOctet = 0;
 	
 	if (!(FirstOctet & 0x01))
-	{
-		SecondOctet = *((uint8_t*)*BufferPos);
-		(*BufferPos)++;
-	}
+	  SecondOctet = *((*BufferPos)++);
 	
 	return (((uint16_t)SecondOctet << 7) | (FirstOctet >> 1));
 }
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.h b/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.h
index 45f29ac21fe3ba1a694254590dc416cb8a508965..194551d03a8627869eb316849e88da8d40a36756 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.h
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/RFCOMM.h
@@ -52,7 +52,7 @@
 		#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 FRAME_POLL_FINAL                        (1 << 5)
+		#define FRAME_POLL_FINAL                        (1 << 4)
 	
 	/* Enums: */
 		/** Enum for the types of RFCOMM frames which can be exchanged on a Bluetooth channel. */
@@ -73,9 +73,9 @@
 				unsigned char LogicalChannel   : 6;
 				unsigned char PollResponse     : 1;
 				unsigned char LastAddressOctet : 1;
-			} Header;
+			} Address;
 			
-			uint8_t FrameType;
+			uint8_t Control;
 		} RFCOMM_Header_t;
 
 	/* Function Prototypes: */
@@ -89,7 +89,8 @@
 			static void RFCOMM_ProcessDISC(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel);
 			static void RFCOMM_ProcessUIH(const RFCOMM_Header_t* const FrameHeader, Bluetooth_Channel_t* const Channel);
 
-			static uint16_t RFCOMM_GetFrameDataLength(void** BufferPos);
+			static uint8_t  RFCOMM_GetFCSValue(const void* FrameStart, uint16_t Length);
+			static uint16_t RFCOMM_GetFrameDataLength(const uint8_t** BufferPos);
 		#endif
 		
 #endif
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c
index ca47f9084a2fd0377db463ef35a15825b119a80b..16317e787ae6782bb10da23e5e2b7c046073b5c1 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c
@@ -28,8 +28,19 @@
   this software.
 */
 
+/** \file
+ *
+ *  SDP Service Attribute definitions. This file contains the attributes
+ *  and attribute tables of all the services the device supports, which can
+ *  then be retrieved by a connected Bluetooth device via the SDP server.
+ */
+
 #include "SDPServices.h"
 
+/** Serial Port Profile attribute, listing the unique service handle of the Serial Port service
+ *  within the device. This handle can then be requested by the SDP client in future transactions
+ *  in lieu of a search UUID list.
+ */
 const struct
 {
 	uint8_t  Header;
@@ -40,6 +51,10 @@ const struct
 		SWAPENDIAN_32(0x00010001),
 	};
 
+/** Serial Port Profile attribute, listing the implemented Service Class UUIDs of the Serial Port service
+ *  within the device. This list indicates all the class UUIDs that apply to the Serial Port service, so that
+ *  a SDP client can search by a generalized class rather than a specific UUID to determine supported services.
+ */
 const struct
 {
 	uint8_t    Header;
@@ -54,6 +69,10 @@ const struct
 		},
 	};
 
+/** Serial Port Profile attribute, listing the Protocols (and their attributes) of the Serial Port service
+ *  within the device. This list indicates what protocols the service is layered on top of, as well as any
+ *  configuration information for each layer.
+ */
 const struct
 {
 	uint8_t               Header;
@@ -77,11 +96,15 @@ const struct
 			(sizeof(ItemUUID_t) + sizeof(Item8Bit_t)),
 			{
 				{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), RFCOMM_UUID},
-				{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_8Bit), 0x00},
+				{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_8Bit), 0x03},
 			},
 		},
 	};
 
+/** Serial Port Profile attribute, listing the Browse Group List UUIDs which this service is a member of.
+ *  Browse Group UUIDs give a way to group together services within a device in a simple heirachy, so that
+ *  a SDP client can progressively narrow down an general browse to a specific service which it requires.
+ */
 const struct
 {
 	uint8_t    Header;
@@ -95,7 +118,10 @@ const struct
 			{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), PUBLICBROWSEGROUP_CLASS_UUID},
 		},
 	};
-	
+
+/** Serial Port Profile attribute, listing the languages (and their encodings) supported
+ *  by the Serial Port service in its text string attributes.
+ */
 const struct
 {
 	uint8_t            Header;
@@ -113,7 +139,8 @@ const struct
 			},
 		},
 	};
-	
+
+/** Serial Port Profile attribute, listing a human readable name of the service. */
 const struct
 {
 	uint8_t Header;
@@ -126,6 +153,7 @@ const struct
 		"Wireless Serial Port",
 	};
 
+/** Serial Port Profile attribute, listing a human readable description of the service. */
 const struct
 {
 	uint8_t Header;
@@ -138,6 +166,9 @@ const struct
 		"Wireless Serial Port Service",
 	};
 
+/** Service Attribute Table for the Serial Port service, linking each supported attribute ID to its data, so that
+ *  the SDP server can retrieve it for transmission back to a SDP client upon request.
+ */
 const ServiceAttributeTable_t PROGMEM SerialPort_Attribute_Table[] =
 	{
 		{.AttributeID = SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE,    .Data = &SerialPort_Attribute_ServiceHandle       },
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c
index c07718e78ce1b22023a7a5d43d2e08a37b7e0dc7..6d8f27036a336ce983131eb7dfe588fdbbf14efa 100644
--- a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c
+++ b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c
@@ -28,6 +28,14 @@
   this software.
 */
 
+/** \file
+ *
+ *  SDP layer module. This module implements a simple Service Discovery
+ *  Protocol server, which can broadcast the device's supported services
+ *  to other Bluetooth devices upon request, so that they can determine
+ *  what services are available.
+ */
+
 #define  INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C
 #include "ServiceDiscoveryProtocol.h"
 
@@ -62,6 +70,7 @@ void SDP_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
 	BT_SDP_DEBUG(2, "-- PDU ID: 0x%02X", SDPHeader->PDU);
 	BT_SDP_DEBUG(2, "-- Param Length: 0x%04X", SDPHeader->ParameterLength);
 
+	/* Dispatch to the correct processing routine for the given SDP packet type */
 	switch (SDPHeader->PDU)
 	{
 		case SDP_PDU_SERVICESEARCHREQUEST: