protected virtual void OnInitialised(BthDs3 Ds3)
 {
     if (LogArrival(Ds3))
     {
         Ds3.Report += new EventHandler <ReportEventArgs>(On_Report);
         Ds3.Start();
     }
 }
        protected virtual BthDs3 Add(Byte Lsb, Byte Msb, String Name)
        {
            BthDs3 Connection = null;

            if (m_Connected.Count < 4)
            {
                Connection        = new BthDs3(this, m_Local, Lsb, Msb);
                Connection.Debug += new EventHandler <DebugEventArgs>(On_Debug);

                m_Connected.Add(Connection.HCI_Handle, Connection);
            }

            return(Connection);
        }
        protected virtual void L2CAP_Worker_Thread(object sender, DoWorkEventArgs e)
        {
            Thread.Sleep(1);

            StringBuilder debug = new StringBuilder();

            Byte[] Buffer = new Byte[64];
            Byte[] L2_DCID, L2_SCID;

            Int32 Transfered = 0;

            L2CAP.Code Event = L2CAP.Code.L2CAP_Reserved;

            LogDebug(String.Format("-- Bluetooth  : L2CAP_Worker_Thread Starting [{0:X2},{1:X2}]", m_BulkIn, m_BulkOut));

            while (IsActive)
            {
                try
                {
                    if (ReadBulkPipe(Buffer, Buffer.Length, ref Transfered) && Transfered > 0)
                    {
                        BthDs3 Connection = Get(Buffer[0], Buffer[1]);

                        if (Buffer[6] == 0x01 && Buffer[7] == 0x00) // Control Channel
                        {
                            if (Enum.IsDefined(typeof(L2CAP.Code), Buffer[8]))
                            {
                                Event = (L2CAP.Code)Buffer[8];

                                switch (Event)
                                {
                                case L2CAP.Code.L2CAP_Command_Reject:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));
                                    break;

                                case L2CAP.Code.L2CAP_Connection_Request:

                                    LogDebug(String.Format(">> {0} [{1:X2}] PSM [{2:X2}]", Event, Buffer[8], Buffer[12]));

                                    L2_SCID = new Byte[2] {
                                        Buffer[14], Buffer[15]
                                    };
                                    L2_DCID = Connection.Set((L2CAP.PSM)Buffer[12], L2_SCID);

                                    L2CAP_Connection_Response(Connection.HCI_Handle.Bytes, Buffer[9], L2_SCID, L2_DCID, 0x00);
                                    LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response, (Byte)L2CAP.Code.L2CAP_Connection_Response));

                                    L2CAP_Configuration_Request(Connection.HCI_Handle.Bytes, m_Id++, L2_SCID);
                                    LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request, (Byte)L2CAP.Code.L2CAP_Configuration_Request));
                                    break;

                                case L2CAP.Code.L2CAP_Connection_Response:

                                    LogDebug(String.Format(">> {0} [{1:X2}] [{2:X2}]", Event, Buffer[8], Buffer[16]));

                                    if (Buffer[16] == 0)     // Success
                                    {
                                        L2_SCID = new Byte[2] {
                                            Buffer[12], Buffer[13]
                                        };
                                        L2_DCID = new Byte[2] {
                                            Buffer[14], Buffer[15]
                                        };

                                        UInt16 DCID = (UInt16)(Buffer[15] << 8 | Buffer[14]);

                                        Connection.Set(L2CAP.PSM.HID_Service, L2_SCID[0], L2_SCID[1], DCID);

                                        L2CAP_Configuration_Request(Connection.HCI_Handle.Bytes, m_Id++, L2_SCID);
                                        LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request, (Byte)L2CAP.Code.L2CAP_Configuration_Request));
                                    }
                                    break;

                                case L2CAP.Code.L2CAP_Configuration_Request:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));

                                    L2_SCID = Connection.Get_SCID(Buffer[12], Buffer[13]);

                                    L2CAP_Configuration_Response(Connection.HCI_Handle.Bytes, Buffer[9], L2_SCID);
                                    LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response, (Byte)L2CAP.Code.L2CAP_Configuration_Response));

                                    if (Connection.SvcStarted)
                                    {
                                        Connection.CanStartHid = true;
                                        Connection.InitReport(Buffer);
                                    }
                                    break;

                                case L2CAP.Code.L2CAP_Configuration_Response:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));

                                    if (Connection.CanStartSvc)
                                    {
                                        UInt16 DCID = BthConnection.DCID++;
                                        L2_DCID = new Byte[2] {
                                            (Byte)((DCID >> 0) & 0xFF), (Byte)((DCID >> 8) & 0xFF)
                                        };

                                        L2CAP_Connection_Request(Connection.HCI_Handle.Bytes, m_Id++, L2_DCID, L2CAP.PSM.HID_Service);
                                        LogDebug(String.Format("<< {0} [{1:X2}] PSM [{2:X2}]", L2CAP.Code.L2CAP_Connection_Request, (Byte)L2CAP.Code.L2CAP_Connection_Request, (Byte)L2CAP.PSM.HID_Service));
                                    }
                                    break;

                                case L2CAP.Code.L2CAP_Disconnection_Request:

                                    LogDebug(String.Format(">> {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.HCI_Handle.Bytes, Buffer[9], L2_SCID, L2_SCID);
                                    LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response, (Byte)L2CAP.Code.L2CAP_Disconnection_Response));
                                    break;

                                case L2CAP.Code.L2CAP_Disconnection_Response:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));

                                    if (Connection.CanStartHid)
                                    {
                                        Connection.SvcStarted = false;
                                        OnInitialised(Connection);
                                    }
                                    break;

                                case L2CAP.Code.L2CAP_Echo_Request:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));
                                    break;

                                case L2CAP.Code.L2CAP_Echo_Response:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));
                                    break;

                                case L2CAP.Code.L2CAP_Information_Request:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));
                                    break;

                                case L2CAP.Code.L2CAP_Information_Response:

                                    LogDebug(String.Format(">> {0} [{1:X2}]", Event, Buffer[8]));
                                    break;

                                default:
                                    break;
                                }
                            }
                        }
                        else if (Buffer[8] == 0xA1 && Buffer[9] == 0x01 && Transfered == 58)
                        {
                            Connection.Parse(Buffer);
                        }
                        else if (Connection.InitReport(Buffer))
                        {
                            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.HCI_Handle.Bytes, m_Id++, L2_SCID, L2_DCID);
                            LogDebug(String.Format("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Request, (Byte)L2CAP.Code.L2CAP_Disconnection_Request));
                        }
                    }
                }

                catch (Exception Ex) { Console.WriteLine(Ex.ToString()); }
            }

            LogDebug("-- Bluetooth  : L2CAP_Worker_Thread Exiting");
        }