/// <summary>
/// Parses an incoming DualShock 4 HID report .
/// </summary>
/// <param name="connection">The device handle the input buffer was received for.</param>
/// <param name="buffer">The HID report in bytes.</param>
/// <param name="transfered">The transfered bytes count.</param>
private void ParseBufferDs4(BthDevice connection, byte[] buffer, int transfered)
{
byte[] L2_DCID, L2_SCID;
if (buffer[6] == 0x01 && buffer[7] == 0x00) // Control Channel
{
if (Enum.IsDefined(typeof(L2CAP.Code), buffer[8]))
{
var Event = (L2CAP.Code)buffer[8];
switch (Event)
{
case L2CAP.Code.L2CAP_Command_Reject:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
case L2CAP.Code.L2CAP_Connection_Request:
Log.DebugFormat(">> {0} [{1:X2}] PSM [{2:X2}]", Event, buffer[8], buffer[12]);
L2_SCID = new byte[2] { buffer[14], buffer[15] };
L2_DCID = connection.SetConnectionType((L2CAP.PSM)buffer[12], L2_SCID);
if (L2CAP.PSM.HID_Interrupt == (L2CAP.PSM)buffer[12])
{
connection.IsStarted = true;
}
L2CAP_Connection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_DCID, 0x00);
Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response,
(byte)L2CAP.Code.L2CAP_Connection_Response);
L2CAP_Configuration_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID);
Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request,
(byte)L2CAP.Code.L2CAP_Configuration_Request);
break;
case L2CAP.Code.L2CAP_Connection_Response:
Log.DebugFormat(">> {0} [{1:X2}] [{2:X2}]", Event, buffer[8], buffer[16]);
break;
case L2CAP.Code.L2CAP_Configuration_Request:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
L2_SCID = connection.Get_SCID(buffer[12], buffer[13]);
L2CAP_Configuration_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID);
Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response,
(byte)L2CAP.Code.L2CAP_Configuration_Response);
if (connection.IsServiceStarted)
{
connection.CanStartHid = true;
}
break;
case L2CAP.Code.L2CAP_Configuration_Response:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
if (connection.IsStarted)
{
OnInitialised(connection);
}
break;
case L2CAP.Code.L2CAP_Disconnection_Request:
Log.DebugFormat(">> {0} [{1:X2}] Handle [{2:X2}{3:X2}]", Event, buffer[8], buffer[15],
buffer[14]);
L2_SCID = new byte[2] { buffer[14], buffer[15] };
L2CAP_Disconnection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_SCID);
Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response,
(byte)L2CAP.Code.L2CAP_Disconnection_Response);
break;
case L2CAP.Code.L2CAP_Disconnection_Response:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
case L2CAP.Code.L2CAP_Echo_Request:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
case L2CAP.Code.L2CAP_Echo_Response:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
case L2CAP.Code.L2CAP_Information_Request:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
case L2CAP.Code.L2CAP_Information_Response:
Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
break;
}
}
}
else if (buffer[8] == 0xA1 && buffer[9] == 0x11 && transfered == 87)
{
// HID report received, parse content and extract gamepad data
connection.ParseHidReport(buffer);
}
else if (connection.InitHidReport(buffer))
{
connection.CanStartHid = true;
}
}