⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btsdp.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

   BTSDP.CPP

Abstract:

    This module implemnts BTh SDP core spec.



   Doron Holan 

   Notes:

   Environment:

   Kernel mode only


Revision History:

*/

#include "common.h"
#include "sdplib.h"

#define SDPI_TAG 'IpdS'

extern SdpDatabase *pSdpDB;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
SdpInterface* pSdp = NULL;
#endif

USHORT SDP_DEFAULT_MTU = 1024;

#define CONFIG_RETRY_DEFAULT    (5)

BOOLEAN ContinuationState::Read(UCHAR *pStream, ULONG streamSize)
{
    // PAGED_CODE();

    size = *pStream;

    // check for out of range size
    if (size > 16) {
        return FALSE; 
    }

    // cont state always at end, so size must match
    if (size != (streamSize - 1)) {
        return FALSE; 
    }

    if (size) {
        memcpy(state, pStream + 1, size);
    }

    return TRUE;
}

void ContinuationState::Write(UCHAR *pStream)
{
    // PAGED_CODE();

    *pStream  = size;
    if (size) {
        memcpy(pStream + 1, state, size); 
    }
}

void ContinuationState::Init(PVOID p)
{ 
    size = sizeof(p);
    RtlCopyMemory(state, &p, size); 
}

PVOID SdpPDU::Read(PVOID pBuffer)
/*++
 
    Reads an SDP PDU header from the stream and returns an unaligned pointer
    to the beginning of the data in the packet
   
    PDU format is
    byte 1:  PDU id
    byte 2-3:  PDU transaction id
    byte 4-5:  PDU parameter length (the remaining size of the buffer)
   
    PDU is in network byte order so we must byte swap the >1 byte values so that
    they make sense
     
  --*/
{
    PUCHAR stream = (PUCHAR) pBuffer;

    pduId = *stream;
    stream++;

    RtlRetrieveUshort(&transactionId, stream);
    transactionId = RtlUshortByteSwap(transactionId);
    stream += sizeof(transactionId);

    RtlRetrieveUshort(&parameterLength, stream);
    parameterLength = RtlUshortByteSwap(parameterLength);
    stream += sizeof(parameterLength);

    return (PVOID) stream;
}

PUCHAR SdpPDU::Write(PUCHAR pBuffer)
/*++

    Writes out an SDP PDU header to the unaligned buffer.
    
  --*/
{
#if DBG
    PUCHAR pOrig = pBuffer;
#endif
    USHORT tmp;

    *pBuffer = pduId;
    pBuffer++;

    tmp = RtlUshortByteSwap(transactionId);
    RtlCopyMemory(pBuffer, &tmp, sizeof(tmp));
    pBuffer += sizeof(tmp);

#if UPF
    HANDLE hKey;
    if (NT_SUCCESS(BthPort_OpenKey(NULL,
                                   STR_REG_MACHINE STR_SOFTWARE_KEYW,
                                   &hKey))) {
        ULONG tmp = 0;
        if (NT_SUCCESS(QueryKeyValue(hKey,
                                     L"InvalidPDU",
                                     &tmp,
                                     sizeof(ULONG))) && tmp != 0) {
            SdpPrint(0, ("***UPF*** using an invalid pdu size (orig %d, override %d) for search\n",
                         (ULONG) parameterLength, (ULONG) parameterLength * 2));
            parameterLength *= 2;
        }

        ZwClose(hKey);
    }
#endif // UPF

    tmp = RtlUshortByteSwap(parameterLength);
    RtlCopyMemory(pBuffer, &tmp, sizeof(tmp));
    pBuffer += sizeof(tmp);

#if DBG
    //
    // Make sure that we did our pointer math correctly
    //
    ASSERT(pBuffer - pOrig == sizeof(*this));
#endif DBG
    
    return pBuffer;
}

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS
SendBrbCompletion(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    )
/*++

    Simple completion routine which sets an event so we can send an irp synch

  --*/
{
    if (Context != NULL) {
        KeSetEvent((PKEVENT) Context, 0, FALSE);
    }
    return STATUS_MORE_PROCESSING_REQUIRED;
}

SdpInterface::SdpInterface()
{
    IoInitializeRemoveLock(&m_RemoveLock, 'DSTB', 0, 0);
    IoAcquireRemoveLock(&m_RemoveLock, (PVOID)-1);
}

SdpInterface::~SdpInterface()
{
    SdpConnection *pCon;
    CList<SdpConnection, FIELD_OFFSET(SdpConnection, entry)> list;

    SdpPrint(SDP_DBG_CONFIG_TRACE, ("~SdpInterface\n"));

    //
    // There should never be any connections in our list when we are destroyed
    // because they should have all been cleared out when we were Stop()'ed
    //
    m_SdpConnectionList.Lock();

    ASSERT(m_SdpConnectionList.IsEmpty());

    while (!m_SdpConnectionList.IsEmpty()) {
        pCon = m_SdpConnectionList.RemoveHead();
        list.AddTail(pCon);
    }
    m_SdpConnectionList.Unlock();

    while (!list.IsEmpty()) {
        pCon = list.RemoveHead();

                delete pCon;
    }
}

NTSTATUS SdpInterface::Start(BThDevice *pBthDevice)
{
    m_pDevice = pBthDevice;
    m_pDevice->AddRef();
    return STATUS_SUCCESS;
}

NTSTATUS SdpInterface::Stop()
/*++

    Iterates over the active connection list and terminates each one

  --*/
{
        m_pDevice->Release();

    _DbgPrintF(DBG_PNP_INFO, ("SDP: waiting on remlock %p\n", &m_RemoveLock));

    IoReleaseRemoveLockAndWait(&m_RemoveLock, (PVOID)-1);
    return STATUS_SUCCESS;
}

SdpConnection*
SdpInterface::FindConnection(
    PVOID hConnection
    )
/*++

    Assumes that the list has been locked.  Will return an SdpConnection based
    on the passed in hConnection.

  --*/
{
    SdpConnection *pCon;

    for (pCon = m_SdpConnectionList.GetHead();
         pCon != NULL;
         pCon = m_SdpConnectionList.GetNext(pCon)) {

        if (pCon->hConnection == hConnection) {
            SdpPrint(SDP_DBG_CON_INFO,
                     ("found SdpConnection %p for connection %p\n",
                      pCon, hConnection));
            return pCon;
        }
    }

    SdpPrint(SDP_DBG_CON_WARNING,
             ("found no SdpConnection for connection %p\n", hConnection));

    return NULL;
}

SdpConnection*
SdpInterface::FindConnection(
    const bt_addr& address,
    BOOLEAN onlyServer
    )
/*++

    Assumes that the list has been locked.  Will return an SdpConnection based
    on the passed in address.   If onlyServer is TRUE, then an SdpConnection
    will only be returned f

  --*/
{
    SdpConnection *pCon;

    for (pCon = m_SdpConnectionList.GetHead();
         pCon != NULL;
         pCon = m_SdpConnectionList.GetNext(pCon)) {

        if (pCon->btAddress == address &&
            ( !onlyServer || (onlyServer && pCon->IsServer()) ) ) {
            SdpPrint(SDP_DBG_CON_INFO,
                     ("found SdpConnection %p for address %04x%08x\n",
                     pCon, GET_NAP(address), GET_SAP(address)));
            return pCon;
        }
    }

    SdpPrint(SDP_DBG_CON_WARNING,
             ("found no SdpConnection for address %04x%08x\n",
             GET_NAP(address), GET_SAP(address)));

    return NULL;
}

void
SdpInterface::FireWmiEvent(
    SDP_SERVER_LOG_TYPE Type,
    bt_addr *pAddress,
    USHORT Mtu
    )
/*++

    Fires a WMI event if SDP_LOGGING is defined

  --*/
{
#ifdef SDP_LOGGING
    PSDP_SERVER_LOG_INFO pLog;

    pLog = (PSDP_SERVER_LOG_INFO)
        ExAllocatePoolWithTag(PagedPool, sizeof(*pLog), SDPI_TAG);

    if (pLog) {
        RtlZeroMemory(pLog, sizeof(*pLog));

        pLog->type = Type;
        if (pAddress) {
            pLog->info.btAddress = *pAddress;
        }
        pLog->mtu = Mtu;
        pLog->dataLength = 0;

        WmiFireEvent(m_pDevice->m_Struct.FunctionalDeviceObject,
                     (LPGUID) &GUID_BTHPORT_WMI_SDP_SERVER_LOG_INFO,
                     0,
                     sizeof(*pLog),
                     pLog);
    }
#endif SDP_LOGGING
}

NTSTATUS SdpInterface::SendBrb(PBRB pBrb)
/*++

    Sends a BRB synchronously down the stack.

  --*/
{
    NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;

    PIRP irp =
        IoAllocateIrp(m_pDevice->m_Struct.FunctionalDeviceObject->StackSize,
                      FALSE);

    if (irp) {
        PIO_STACK_LOCATION stack;
        KEVENT event;

        stack = IoGetNextIrpStackLocation(irp);
        stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        stack->Parameters.DeviceIoControl.IoControlCode =
            IOCTL_INTERNAL_BTH_SUBMIT_BRB;
        stack->Parameters.Others.Argument1 = pBrb;

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);

        IoSetCompletionRoutine(irp,
                               SendBrbCompletion,
                               (PVOID) &event,
                               TRUE,
                               TRUE,
                               TRUE);

        status = IoCallDriver(m_pDevice->m_Struct.FunctionalDeviceObject, irp);

        if (status == STATUS_PENDING) {
            SdpPrint(SDP_DBG_BRB_INFO,
                     ("SendBrb pended, waiting on event %p for BRB %p (type %d)\n",
                      &event, pBrb, pBrb->BrbHeader.Type));

            KeWaitForSingleObject(&event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);

            SdpPrint(SDP_DBG_BRB_INFO,
                     ("SendBrb pended, end wait on event %p\n", &event));

            status = irp->IoStatus.Status;
        }

        IoFreeIrp(irp);
    }
    else {
        SdpPrint(SDP_DBG_BRB_ERROR, ("SendBrb could not alloc an irp\n"));
    }

    SdpPrint(SDP_DBG_BRB_INFO, ("SendBrb (%p - %d) status 0x%x\n",
             pBrb, pBrb->BrbHeader.Type, status));

    return status;
}

NTSTATUS
SdpInterface::SendBrbAsync(
    PIRP pIrp,
    PBRB pBrb,
    PIO_COMPLETION_ROUTINE Routine,
    PVOID pContext,
    PVOID pArg1,
    PVOID pArg2,
    PVOID pArg3,
    PVOID pArg4
    )
{                                                                     
    PIO_STACK_LOCATION stack;
    KEVENT event;
    NTSTATUS status;

    SdpPrint(SDP_DBG_BRB_INFO, ("SendBrbAsync, irp %p, brb %p, routine %p\n",
             pIrp, pBrb, Routine));

    IoReuseIrp(pIrp, STATUS_SUCCESS);

    stack = IoGetNextIrpStackLocation(pIrp);
    stack->Parameters.Others.Argument1 = pArg1;
    stack->Parameters.Others.Argument2 = pArg2;
    stack->Parameters.Others.Argument3 = pArg3;
    stack->Parameters.Others.Argument4 = pArg4;
    IoSetNextIrpStackLocation(pIrp);

    stack = IoGetNextIrpStackLocation(pIrp);
    stack->Parameters.Others.Argument1 = pBrb;
    stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    stack->Parameters.DeviceIoControl.IoControlCode =
        IOCTL_INTERNAL_BTH_SUBMIT_BRB;

    IoSetCompletionRoutine(pIrp,
                           Routine,
                           pContext,
                           TRUE,
                           TRUE,
                           TRUE);

    status = IoCallDriver(m_pDevice->m_Struct.FunctionalDeviceObject, pIrp);

    SdpPrint(SDP_DBG_BRB_INFO, ("SendBrbAsync returns 0x%x\n", status));

    return status;
}
#endif // UNDER_CE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -