+/** Opens a bluetooth channel to the currently connected remote device, so that data can be exchanged.\r
+ *\r
+ * \note The channel is not immediately opened when this function returns - it must undergo a two way\r
+ * connection and configuration process first as the main Bluetooth stack processing task is\r
+ * repeatedly called. The returned channel is unusable by the user application until its State\r
+ * element has progressed to the Open state.\r
+ *\r
+ * \param PSM PSM of the service that the channel is to be opened for\r
+ *\r
+ * \return Pointer to the channel information structure of the opened channel, or NULL if no free channels\r
+ */\r
+Bluetooth_Channel_t* Bluetooth_OpenChannel(uint16_t PSM)\r
+{\r
+ Bluetooth_Channel_t* ChannelData = NULL;\r
+\r
+ /* Search through the channel information list for a free channel item */\r
+ for (uint8_t i = 0; i < BLUETOOTH_MAX_OPEN_CHANNELS; i++)\r
+ {\r
+ if (Bluetooth_Connection.Channels[i].State == Channel_Closed)\r
+ {\r
+ ChannelData = &Bluetooth_Connection.Channels[i];\r
+ \r
+ /* Set the new channel structure's local channel number to a unique value within the connection orientated\r
+ channel address space */\r
+ ChannelData->LocalNumber = (BT_CHANNELNUMBER_BASEOFFSET + i);\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* If no free channel item was found in the list, all channels are occupied - abort */\r
+ if (ChannelData == NULL)\r
+ return NULL;\r
+\r
+ /* Reset and fill out the allocated channel's information structure with defaults */\r
+ ChannelData->RemoteNumber = 0;\r
+ ChannelData->PSM = PSM;\r
+ ChannelData->LocalMTU = MAXIMUM_CHANNEL_MTU;\r
+ ChannelData->State = Channel_WaitConnectRsp;\r
+ \r
+ struct\r
+ {\r
+ BT_Signal_Header_t SignalCommandHeader;\r
+ BT_Signal_ConnectionReq_t ConnectionRequest;\r
+ } PacketData;\r
+\r
+ /* Fill out the Signal Command header in the response packet */\r
+ PacketData.SignalCommandHeader.Code = BT_SIGNAL_CONNECTION_REQUEST;\r
+ PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignallingIdentifier;\r
+ PacketData.SignalCommandHeader.Length = sizeof(PacketData.ConnectionRequest);\r
+ \r
+ /* Fill out the Connection Request in the response packet */\r
+ PacketData.ConnectionRequest.PSM = PSM;\r
+ PacketData.ConnectionRequest.SourceChannel = ChannelData->LocalNumber;\r
+ \r
+ Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);\r
+\r
+ BT_ACL_DEBUG(1, ">> L2CAP Connection Request", NULL);\r
+ BT_ACL_DEBUG(2, "-- PSM 0x%04X", PacketData.ConnectionRequest.PSM);\r
+ BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.ConnectionRequest.SourceChannel);\r
+\r
+ return ChannelData;\r
+}\r
+\r
+/** Closes a bluetooth channel that is open to the currently connected remote device, so that no further data\r
+ * can be exchanged.\r
+ *\r
+ * \note The channel is not immediately closed when this function returns - it must undergo an asynchronous\r
+ * disconnection process first as the main Bluetooth stack processing task is repeatedly called. The\r
+ * returned channel is unusable by the user application upon return however the channel is not completely\r
+ * closed until its State element has progressed to the Closed state.\r
+ *\r
+ * \param Channel Channel information structure of the channel to close\r
+ */\r
+void Bluetooth_CloseChannel(Bluetooth_Channel_t* Channel)\r
+{\r
+ /* Don't try to close a non-existing or already closed channel */\r
+ if ((Channel == NULL) || (Channel->State == Channel_Closed))\r
+ return;\r
+\r
+ /* Set the channel's state to the start of the teardown process */\r
+ Channel->State = Channel_WaitDisconnect;\r
+\r
+ struct\r
+ {\r
+ BT_Signal_Header_t SignalCommandHeader;\r
+ BT_Signal_DisconnectionReq_t DisconnectionRequest;\r
+ } PacketData;\r
+ \r
+ /* Fill out the Signal Command header in the response packet */\r
+ PacketData.SignalCommandHeader.Code = BT_SIGNAL_DISCONNECTION_REQUEST;\r
+ PacketData.SignalCommandHeader.Identifier = ++Bluetooth_Connection.SignallingIdentifier;\r
+ PacketData.SignalCommandHeader.Length = sizeof(PacketData.DisconnectionRequest);\r
+\r
+ /* Fill out the Disconnection Request in the response packet */\r
+ PacketData.DisconnectionRequest.DestinationChannel = Channel->RemoteNumber;\r
+ PacketData.DisconnectionRequest.SourceChannel = Channel->LocalNumber;\r
+\r
+ Bluetooth_SendPacket(&PacketData, sizeof(PacketData), NULL);\r
+ \r
+ BT_ACL_DEBUG(1, ">> L2CAP Disconnection Request", NULL);\r
+ BT_ACL_DEBUG(2, "-- Destination Channel: 0x%04X", PacketData.DisconnectionRequest.DestinationChannel); \r
+ BT_ACL_DEBUG(2, "-- Source Channel: 0x%04X", PacketData.DisconnectionRequest.SourceChannel); \r
+}\r
+\r
+/** Internal Bluetooth stack Signal Command processing routine for a Connection Request command.\r
+ *\r
+ * \param SignalCommandHeader Pointer to the start of the received packet's Signal Command header\r
+ */\r
+static inline void Bluetooth_Signal_ConnectionReq(BT_Signal_Header_t* SignalCommandHeader)\r