void DecodeCallBack::onDebug ( const PDU& pdu) 
{
    const uint8 *buf = pdu.data ();
    size_t len = pdu.size ();

#ifdef THREADING_WORKAROUND
    CriticalSection::Lock cs_lock (cs);
#endif
#if 0
    ASSERT (len != 0);

    if (buf[len - 1] == NUL)
    {
        printlf ("debug");
        printlf (" \"");
        while (len--)
        {
            printChar (*buf++);
        }
        printlf ("\"\n");
    }
    else
    {
        printlf ("debug");
        for (; len != 0; --len)
        {
            printlf (" 0x%02x", *buf++);
        }
        printlf ("\n");
    }
#else   
    decodeDebug(buf, len);
#endif
}
void DecodeCallBack::onHCIEvent(const PDU &pdu) 
{
    HCIEventPDU eventPdu(pdu);
    BadPDUReason failCode;
    uint32 length = HCIPDUFactory::decomposeEventPDU(pdu, 0, failCode);
    
    if ( length == 0 )
    {
        printBadPDU (failCode, pdu.data(), pdu.size() );
        return;
    }

    if (eventPdu.get_event_code() == HCI_EV_NUMBER_COMPLETED_PKTS)
    {
        aclEngine->nocp(pdu);
    }
    else if (eventPdu.get_event_code() == HCI_EV_COMMAND_COMPLETE)
    {
        HCICommandCompletePDU cc_pdu(pdu);
        if (cc_pdu.get_op_code() == HCI_READ_BUFFER_SIZE)
        {
            HCI_READ_BUFFER_SIZE_RET_T_PDU rbs_pdu(cc_pdu);
            aclEngine->setBufferSizes(rbs_pdu);
            scoEngine->setBufferSizes(rbs_pdu);
        }
    }

    if (length != 0)
    {
        uint32 *pa = new uint32 [length];

        if (pa == 0)
        {
            return;
        }

        pa [0] = length;
        length = HCIPDUFactory::decomposeEventPDU(pdu, pa, failCode);

#ifdef THREADING_WORKAROUND
        CriticalSection::Lock cs_lock (cs);
#endif
#if 0
        unsigned i;

        ASSERT (pa[0] >= 2);
        ASSERT (ec == pa[1]);

        printlf ("App: received event, code 0x%02x, pa[] =", ec);
        for (i = 2; i < pa[0]; ++i)
        {
            printlf (" 0x%lx", (ul) pa[i]);
        }
        printlf (" [%u args]\n", pa[0] - 2);
#else
        decodeEvt (pa);
#endif
    }
}
// Send a PDU that requires HCI tunnelling for manufacturer extensions
void BlueCoreTransportImplementation::sendTunnel ( const PDU& aPacket )
{
    if (tunnel)
    {
        uint8 data[HCI_TUNNEL_HEADER_SIZE+HCI_TUNNEL_MAX_PAYLOAD];
        size_t offset = 0;
        while ( offset < aPacket.size() )
        {
			size_t lLength = aPacket.size() - offset;
			while (1)
			{
				// Calculate the payload length and descriptor
				uint8 descriptor = aPacket.channel();
				if (offset == 0)
					descriptor |= HCI_TUNNEL_FIRST;

				if (HCI_TUNNEL_MAX_PAYLOAD < lLength)
					lLength = HCI_TUNNEL_MAX_PAYLOAD;

				if (offset + lLength == aPacket.size())
					descriptor |= HCI_TUNNEL_LAST;

				// Build and send the HCI command for this fragment
				data[0] = uint8(HCI_TUNNEL_COMMAND & 0xff);
				data[1] = uint8(HCI_TUNNEL_COMMAND >> 8);
				data[2] = uint8(lLength + 1);
				data[3] = descriptor;
				memcpy(data + HCI_TUNNEL_HEADER_SIZE, aPacket.data() + offset, lLength);
				PDU p(PDU::hciCommand, data, HCI_TUNNEL_HEADER_SIZE + lLength);
				if (pdu_size_forbidden(p))
				{
					// can't send pdu of this length. try one size smaller.
					--lLength;
				}
				else
				{
					sendpdu(p);
					break;
				}
			}

            offset += lLength;
        }
    }
}
static bool ignoresFlowControl ( const PDU& pdu )
{
    switch ( pdu.channel() )
    {
    case PDU::hciCommand :
        {
        HCICommandPDU cmd ( pdu.data() , pdu.size() );
        switch ( cmd.get_op_code() )
        {
		case HCI_ACCEPT_CONNECTION_REQ:
		case HCI_REJECT_CONNECTION_REQ:
        case HCI_LINK_KEY_REQ_REPLY:
        case HCI_LINK_KEY_REQ_NEG_REPLY:
        case HCI_PIN_CODE_REQ_REPLY:
        case HCI_PIN_CODE_REQ_NEG_REPLY:
		case HCI_ACCEPT_SYNCHRONOUS_CONN_REQ:
		case HCI_REJECT_SYNCHRONOUS_CONN_REQ:
		case HCI_IO_CAPABILITY_RESPONSE:
		case HCI_USER_CONFIRMATION_REQUEST_REPLY:
		case HCI_USER_CONFIRMATION_REQUEST_NEG_REPLY:
		case HCI_USER_PASSKEY_REQUEST_REPLY:
		case HCI_USER_PASSKEY_REQUEST_NEG_REPLY:
		case HCI_REMOTE_OOB_DATA_REQUEST_REPLY:
		case HCI_REMOTE_OOB_DATA_REQUEST_NEG_REPLY:
		case HCI_IO_CAPABILITY_REQUEST_NEG_REPLY:
        case HCI_RESET:
        case HCI_HOST_NUM_COMPLETED_PACKETS:
        case HCI_ULP_LONG_TERM_KEY_REQUESTED_REPLY:
        case HCI_ULP_LONG_TERM_KEY_REQUESTED_NEGATIVE_REPLY:
        case 0xFC00:
            return true;
            break;
        default:
            break;
        }
        break;
        }
    default:
        break;
    };
    return false;
}
void DecodeCallBack::onLMPdebug(const PDU &pdu)
{
    const uint8 *buf = pdu.data ();
    size_t len = pdu.size ();

#ifdef THREADING_WORKAROUND
    CriticalSection::Lock cs_lock (cs);
#endif
#if 0
    ASSERT (len != 0);

    printlf ("lmp");
    for (; len != 0; --len)
    {
        printlf (" 0x%02x", *buf++);
    }
    printlf ("\n");
#else
    decodeLMPdebug (buf, len, NULL);
#endif
}
void DecodeCallBack::onHQRequest(const PDU &pdu) 
{
    BadPDUReason failCode;

    uint32 length = HCIPDUFactory::decomposeHQ_PDU (pdu, 0, failCode);

    if (length == 0)
    {
        printBadPDU (failCode, pdu.data(), pdu.size() );
    }
    else
    {
        uint32 *pa = new uint32 [length];

        if (pa == 0)
        {
            return;
        }

        pa [0] = length;
        length = HCIPDUFactory::decomposeHQ_PDU(pdu, pa, failCode);
    
#ifdef THREADING_WORKAROUND
        CriticalSection::Lock cs_lock (cs);
#endif
#if 0
        size_t i;
        ASSERT (pa[0] >= 4);

        printlf ("App: received hq indication; cmd 0x%lx with seqno 0x%lx, status %lu, pa[] =", (ul) pa[1], (ul) pa[2], (ul) pa[3]);
        for (i = 4; i < pa[0]; ++i)
        {
            printlf (" 0x%lx", (ul) pa[i]);
        }
        printlf (" [%u args]\n", pa[0] - 4);
#else
        decodeHQ (pa);
#endif
    }
}
/*virtual*/ void BCSPH5Transport::recvOther(const PDU &aPacket)
{
	recvData(aPacket.channel(), aPacket.data(), aPacket.size());
}