in ScpControl/Bluetooth/BthDongle.Tasks.cs [246:511]
private void ParseBufferDs3(BthDevice connection, L2CapDataPacket packet)
{
byte[] L2_DCID;
byte[] L2_SCID;
if (packet.IsControlChannel) // Control Channel
{
if (packet.IsValidSignallingCommandCode)
{
var Event = packet.SignallingCommandCode;
switch (Event)
{
#region L2CAP_Command_Reject
case L2CAP.Code.L2CAP_Command_Reject:
Log.DebugFormat(">> {0}", Event);
break;
#endregion
#region L2CAP_Connection_Request
case L2CAP.Code.L2CAP_Connection_Request:
Log.DebugFormat(">> {0} with PSM [{1}] [CID: {2}]", Event,
packet.ProtocolServiceMultiplexer,
packet.ChannelId);
L2_SCID = packet.SourceChannelIdentifier;
// set HID command channel for current connection
L2_DCID = connection.SetConnectionType(packet.ProtocolServiceMultiplexer, L2_SCID);
// send response with connection pending
L2CAP_Connection_Response(connection.HciHandle.Bytes,
packet.ChannelId, L2_SCID, L2_DCID,
L2CAP.ConnectionResponseResult.ConnectionPending,
L2CAP.ConnectionResponseStatus.AuthorisationPending);
Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
packet.ChannelId);
// send response with connection successful
L2CAP_Connection_Response(connection.HciHandle.Bytes,
packet.ChannelId, L2_SCID, L2_DCID,
L2CAP.ConnectionResponseResult.ConnectionSuccessful);
Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
packet.ChannelId);
// send configuration request
L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID);
Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Request,
_l2CapDataIdentifier - 1);
break;
#endregion
#region L2CAP_Connection_Response
case L2CAP.Code.L2CAP_Connection_Response:
Log.DebugFormat(">> {0} [Result: {1}] [CID: {2}]", Event, packet.Result, packet.ChannelId);
var result = packet.Result;
L2_SCID = packet.SourceChannelIdentifier;
Log.DebugFormat("-- L2_SCID = [{0:X2}, {1:X2}]", L2_SCID[0], L2_SCID[1]);
L2_DCID = packet.DestinationChannelIdentifier;
Log.DebugFormat("-- L2_DCID = [{0:X2}, {1:X2}]", L2_DCID[0], L2_DCID[1]);
// interpret result
switch ((L2CAP.ConnectionResponseResult) result)
{
case L2CAP.ConnectionResponseResult.ConnectionSuccessful:
// destination channel identifier
var DCID = packet.DestinationChannelIdentifierUInt16;
Log.DebugFormat("-- DCID (shifted) = {0:X4}", DCID);
// set HID service channel for current connection
connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_SCID[0], L2_SCID[1], DCID);
// send configuration request
L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++,
L2_SCID);
Log.DebugFormat("<< {0} [CID: {1}]",
L2CAP.Code.L2CAP_Configuration_Request,
packet.ChannelId);
break;
case L2CAP.ConnectionResponseResult.ConnectionPending:
Log.DebugFormat("-- Connection pending for pad {0}",
connection.PadId.ToString().ToLower());
break;
case L2CAP.ConnectionResponseResult.ConnectionRefusedPsmNotNupported:
Log.ErrorFormat(
"Requested Protocol Service Multiplexer not supported on device {0}",
connection.HostAddress);
break;
case L2CAP.ConnectionResponseResult.ConnectionRefusedSecurityBlock:
Log.ErrorFormat("Connection refused for security reasons on device {0}",
connection.HostAddress);
break;
case L2CAP.ConnectionResponseResult.ConnectionRefusedNoResourcesAvailable:
Log.ErrorFormat("Connection failed for device {0}: no resources available",
connection.HostAddress);
break;
default:
Log.WarnFormat("Unknown result: {0}", result);
break;
}
break;
#endregion
#region L2CAP_Configuration_Request
case L2CAP.Code.L2CAP_Configuration_Request:
Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);
L2_SCID = connection.Get_SCID(packet.SourceChannelIdentifier);
L2CAP_Configuration_Response(connection.HciHandle.Bytes,
packet.ChannelId, L2_SCID);
Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Response,
packet.ChannelId);
if (connection.IsServiceStarted)
{
connection.CanStartHid = true;
connection.InitHidReport(packet.RawBytes);
}
break;
#endregion
#region L2CAP_Configuration_Response
case L2CAP.Code.L2CAP_Configuration_Response:
Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);
Log.DebugFormat("-- MTU = {0}", packet.MaximumTransmissionUnit);
if (connection.CanStartService)
{
L2_DCID = L2CapDataPacket.UInt16ToBytes(BthConnection.Dcid++);
if (!connection.IsFake)
{
L2CAP_Connection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_DCID,
L2CAP.PSM.HID_Service);
Log.DebugFormat("<< {0} with PSM [{1}] [CID: {2}]",
L2CAP.Code.L2CAP_Connection_Request,
L2CAP.PSM.HID_Service,
_l2CapDataIdentifier - 1);
}
else
{
connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_DCID);
connection.CanStartService = false;
OnInitialised(connection);
}
}
break;
#endregion
#region L2CAP_Disconnection_Request
case L2CAP.Code.L2CAP_Disconnection_Request:
Log.DebugFormat(">> {0} Handle [{1}]", Event, packet.SourceChannelIdentifier);
L2_SCID = packet.SourceChannelIdentifier;
L2CAP_Disconnection_Response(connection.HciHandle.Bytes,
packet.ChannelId, L2_SCID, L2_SCID);
Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Response);
break;
#endregion
#region L2CAP_Disconnection_Response
case L2CAP.Code.L2CAP_Disconnection_Response:
Log.DebugFormat(">> {0}", Event);
if (connection.CanStartHid)
{
connection.IsServiceStarted = false;
OnInitialised(connection);
}
break;
#endregion
#region L2CAP_Echo_Request
case L2CAP.Code.L2CAP_Echo_Request:
Log.DebugFormat(">> {0}", Event);
break;
#endregion
#region L2CAP_Echo_Response
case L2CAP.Code.L2CAP_Echo_Response:
Log.DebugFormat(">> {0}", Event);
break;
#endregion
#region L2CAP_Information_Request
case L2CAP.Code.L2CAP_Information_Request:
Log.DebugFormat(">> {0}", Event);
break;
#endregion
#region L2CAP_Information_Response
case L2CAP.Code.L2CAP_Information_Response:
Log.DebugFormat(">> {0}", Event);
break;
#endregion
}
}
}
else if (packet.IsHidInputReport)
{
// HID report received, parse content and extract gamepad data
connection.ParseHidReport(packet.RawBytes);
}
else if (connection.InitHidReport(packet.RawBytes))
{
connection.CanStartHid = true;
L2_DCID = connection.Get_DCID(L2CAP.PSM.HID_Service);
L2_SCID = connection.Get_SCID(L2CAP.PSM.HID_Service);
L2CAP_Disconnection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID, L2_DCID);
Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Request);
}
}