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

📄 bthsco.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:
{
    if (!pCall) {
        return;
    }

    SVSUTIL_ASSERT(!pCall->pNext);
    SVSUTIL_ASSERT(!pCall->pPrev);

    if (pCall->hEvent) {
        CloseHandle(pCall->hEvent);
    }
    delete pCall;
}

//
// return NULL     if pCall not found in list.
// return non-NULL if pCall     found in list
//
// if fCallType is zero, then it is not checked.
//
static Call* CallVerify(Call* pCall, unsigned char fCallType)
{
    SVSUTIL_ASSERT(gpLayerState->IsLocked());

    Call *pRunner = gpLayerState->pCalls;

    while (pRunner && (pRunner != pCall))
    {
        pRunner = pRunner->pNext;
    }

    // check fCallType field
    if (pRunner && fCallType) {
        if (pRunner->fCallType != fCallType) {
            pRunner = NULL;
        }
    }

    return pRunner;
}

static void CallInsert (Call* pCall)
{
    if (!gpLayerState || !pCall) {
        return;
    }

    SVSUTIL_ASSERT(gpLayerState->IsLocked());

    // insert into head
    pCall->pPrev = NULL;
    if (gpLayerState->pCalls) {
        pCall->pNext = gpLayerState->pCalls;
        gpLayerState->pCalls->pPrev = pCall;
    } else {
        pCall->pNext = NULL;
    }
    gpLayerState->pCalls = pCall;
}

static void CallRemove (Call* pCall)
{
    if (!gpLayerState || !pCall) {
        return;
    }

    SVSUTIL_ASSERT(gpLayerState->IsLocked());

    Call *pPrevCall = pCall->pPrev;
    Call *pNextCall = pCall->pNext;

    if (pNextCall) {
        pNextCall->pPrev = pPrevCall;
    }
    if (pPrevCall) {
        pPrevCall->pNext = pNextCall;
    } else {
        SVSUTIL_ASSERT(gpLayerState->pCalls == pCall);
        gpLayerState->pCalls = pNextCall;
    }

    pCall->pNext = NULL;
    pCall->pPrev = NULL;
}

// write any output data that is in the Call struct 
// to the SCO_USER_CALL struct.
static void CallSetUserData(SCO_USER_CALL *pUserCall, Call *pCall)
{
    SVSUTIL_ASSERT(pUserCall);
    SVSUTIL_ASSERT(pCall);
    if (!pUserCall || !pCall) {
        return;
    }

    switch (pUserCall->dwUserCallType)
    {
        case UCT_CONNECT:
            SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_CONNECT);
            pUserCall->uParameters.Connect.hScoConnection = pCall->uParameters.Connect.hScoConnection;
            break;

        case UCT_READ_VOICE_SETTING:
            SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_READ_VOICE_SETTING);
            pUserCall->uParameters.ReadVoiceSetting.VoiceSetting.usSetting = pCall->uParameters.ReadVoiceSetting.Setting.usSetting;
            break;

        case UCT_RECV_CONNECTION:
            SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_ACCEPT_INCOMING_CONNECTION);
            pUserCall->uParameters.RecvConnection.Address        = pCall->uParameters.AcceptIncomingConnection.Address;
            pUserCall->uParameters.RecvConnection.hScoConnection = pCall->uParameters.AcceptIncomingConnection.hScoConnection;
            break;

        // pCall does not have any return data for pUserCall
        // i.e. there are no OUT parameters
        case UCT_WRITE_VOICE_SETTING:
        case UCT_DISCONNECT:
        case UCT_WRITE_PACKET:
            break;

        default:
            IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: CallSetUserData :: unknown dwUserCallType\n"));
            SVSUTIL_ASSERT(!"unknown eUserCallType");
            break;
    }
}

static void CallSignal (Call *pCall, int iResult)
{
    if (!pCall) {
        return;
    }

    SVSUTIL_ASSERT(!pCall->pNext);
    SVSUTIL_ASSERT(!pCall->pPrev);

    pCall->iResult = iResult;

    SCO_USER_CALL *pUserCall = pCall->pUserCall;
    if (pUserCall) {
        DWORD dwOrgPerm = SetProcPermissions((DWORD)-1);
        pUserCall->iResult = iResult;
        if (pUserCall->hEvent) {
            if (iResult == ERROR_SUCCESS) {
                CallSetUserData(pUserCall, pCall);
            }
            SetEvent(pUserCall->hEvent);
        }
        SetProcPermissions(dwOrgPerm);
    }

    if (pCall->hEvent) {
        SetEvent(pCall->hEvent);
    } else {
        // if there is no pCall->hEvent, then that means that no one is waiting
        // on this pCall, which means no one has taken responsibility to delete
        // it. so we shall delete it now.
        CallDelete(pCall);
    }
}

static Call* CallFindByUserCall(SCO_USER_CALL *pUserCall)
{
    SVSUTIL_ASSERT(gpLayerState->IsLocked());
    Call *pCall = gpLayerState->pCalls;
    while (pCall)
    {
        if (pCall->pUserCall == pUserCall)
            return pCall;
        pCall = pCall->pNext;
    }
    return NULL;
}


//
// Init and Uninit functions:
//
// int sco_InitializeOnce      (void)
// int sco_UninitializeOnce    (void)
// int sco_CreateDriverInstance(void)
// int sco_CloseDriverInstance (void)
//
// int sco_Bind(void *pUserData, SCO_CALLBACKS *pCallbacks, SCO_INTERFACE *pInterface)
// int sco_Unbind()
//

int sco_InitializeOnce(void)
{
    DebugInit();

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() entered\n"));

    if (gpLayerState) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_InitializeOnce() return ERROR_ALREADY_EXISTS\n"));
        return ERROR_ALREADY_EXISTS;
    }

    SVSUTIL_ASSERT(!ghModBtd);
    ghModBtd = LoadLibrary(L"btd.dll");
    if (!ghModBtd) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() : LoadLibrary(btd.dll) failed\n"));
        return GetLastError();
    }
    gpfHCI_EstablishDeviceContext = (HCI_EstablishDeviceContext_t) GetProcAddress(ghModBtd, L"HCI_EstablishDeviceContext");
    gpfHCI_CloseDeviceContext     = (HCI_CloseDeviceContext_t)     GetProcAddress(ghModBtd, L"HCI_CloseDeviceContext");
    if (!gpfHCI_EstablishDeviceContext || !gpfHCI_CloseDeviceContext) {
        FreeLibrary(ghModBtd);
        ghModBtd = NULL;
        gpfHCI_EstablishDeviceContext = NULL;
        gpfHCI_CloseDeviceContext     = NULL;
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() : btd.dll is not exporting required functions\n"));
        return ERROR_PROC_NOT_FOUND;
    }

    gpLayerState = new SCO;
    if (!gpLayerState) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_InitializeOnce() return ERROR_OUTOFMEMORY\n"));
        return ERROR_OUTOFMEMORY;
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() return ERROR_SUCCESS\n"));
    return ERROR_SUCCESS;
}

int sco_UninitializeOnce (void)
{
	if (!gpLayerState) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ERROR_SERVICE_DOES_NOT_EXIST\n"));
        return ERROR_SERVICE_DOES_NOT_EXIST;
    }
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_UninitializeOnce() entered\n"));

    gpLayerState->Lock();

    // sco_CloseDriverInstance() has to be called before sco_UninitializeOnce()
    if (gpLayerState->fIsRunning) {
        IFDBG(DebugOut(DEBUG_ERROR, L"SCO :: sco_UninitializeOnce ERROR_DEVICE_IN_USE\n"));
        gpLayerState->Unlock();
        return ERROR_DEVICE_IN_USE;
    }

    // want gpLayerState to be NULL by the time we Unlock() so...
    SCO *pTemp = gpLayerState;
    gpLayerState = NULL;
    pTemp->Unlock();
    delete pTemp;

    if (ghModBtd) {
        FreeLibrary(ghModBtd);
        ghModBtd = NULL;
        gpfHCI_EstablishDeviceContext = NULL;
        gpfHCI_CloseDeviceContext     = NULL;
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_UninitializeOnce() return ERROR_SUCCESS\n"));

    DebugDeInit();

    return ERROR_SUCCESS;
}

int sco_CreateDriverInstance (void) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance\n"));

    gpLayerState->Lock();

	if (gpLayerState->hClosingEvent) {
		CloseHandle(gpLayerState->hClosingEvent);
		gpLayerState->hClosingEvent = NULL;
	}
	
	gpLayerState->hClosingEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (gpLayerState->fIsRunning) {
        gpLayerState->Unlock();
        return ERROR_ALREADY_EXISTS;
    }

    HCI_CALLBACKS hc;
    HCI_EVENT_INDICATION hei;

    memset (&hc, 0, sizeof (hc));
    memset (&hei, 0, sizeof (hei));

    // event handlers
    hei.hci_ConnectionCompleteEvent         = sco_ConnectionComplete_Event;
    hei.hci_DisconnectionCompleteEvent      = sco_DisconnectionComplete_Event;
    hei.hci_StackEvent                      = sco_Stack_Event;
    hei.hci_ConnectionRequestEvent          = sco_ConnectionRequest_Event;
    hei.hci_NumberOfCompletedPacketsEvent   = sco_NumberOfCompletedPackets_Event;
    hei.hci_DataPacketUp                    = sco_DataPacketUp_Event;

    // callbacks
    hc.hci_AddSCOConnection_Out             = sco_AddSCOConnection_Out;
    hc.hci_Disconnect_Out                   = sco_Disconnect_Out;
    hc.hci_CallAborted                      = sco_CallAborted_Out;
    hc.hci_WriteVoiceSetting_Out            = sco_WriteVoiceSetting_Out;
    hc.hci_ReadVoiceSetting_Out             = sco_ReadVoiceSetting_Out;
    hc.hci_AcceptConnectionRequest_Out      = sco_AcceptConnectionRequest_Out;
    hc.hci_DataPacketDown_Out               = sco_DataPacketDown_Out;
    hc.hci_WriteSCOFlowControlEnable_Out    = sco_WriteSCOFlowControlEnable_Out;
    hc.hci_ReadSCOFlowControlEnable_Out     = sco_ReadSCOFlowControlEnable_Out;

    SVSUTIL_ASSERT(gpfHCI_EstablishDeviceContext);
    int iErr = gpfHCI_EstablishDeviceContext (  gpLayerState, 
                                                BTH_CONTROL_ROUTE_BY_LINKTYPE, 
                                                NULL, 
                                                0, 
                                                BT_LINK_TYPE_SCO,
                                                &hei, 
                                                &hc, 
                                                &gpLayerState->hci_if, 
                                                &gpLayerState->cHciHeaders, 
                                                &gpLayerState->cHciTrailers, 
                                                &gpLayerState->hHCI
                                             );
    if (ERROR_SUCCESS != iErr) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: Could not create device context\n"));
        gpLayerState->Unlock();
        return iErr;
    }

    gpLayerState->fIsRunning = TRUE;

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: HCI_EstablishDeviceContext successful\n"));

    //
    // determine whether the stack is connected
    //

    int fConnected = FALSE;

    __try {
        int dwRet = 0;

        BT_LAYER_IO_CONTROL pFunction = gpLayerState->hci_if.hci_ioctl;
        HANDLE hHCI = gpLayerState->hHCI;

        gpLayerState->AddRef ();
        gpLayerState->Unlock ();

        pFunction (hHCI, BTH_STACK_IOCTL_GET_CONNECTED, 0, NULL, sizeof(fConnected), (char *)&fConnected, &dwRet);

        gpLayerState->Lock ();
        gpLayerState->DelRef ();

        if ((dwRet == sizeof(fConnected)) && fConnected)
            gpLayerState->fConnected = TRUE;
    } __except (1) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_CreateDriverInstance :: exception in hci_ioctl BTH_STACK_IOCTL_GET_CONNECTED\n"));
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ConnectionState = %s\n", gpLayerState->fConnected ? L"CONNECTED" : L"DISCONNECTED"));

    gpLayerState->Unlock();

    if (fConnected) {
        // if we are not connected right now, then StackInitDevice() will be invoked on BTH_STACK_UP event
        StackInitDevice();
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ERROR_SUCCESS\n"));

    return ERROR_SUCCESS;
}


int sco_CloseDriverInstance (void) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance\n"));

    gpLayerState->Lock ();
    if (! gpLayerState->fIsRunning) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: ERROR_SERVICE_NOT_ACTIVE\n"));
        gpLayerState->Unlock ();

        return ERROR_SERVICE_NOT_ACTIVE;
    }

	SetEvent(gpLayerState->hClosingEvent);
    gpLayerState->fIsRunning = FALSE;

    while (gpLayerState->GetRefCount () > 1) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: (RefCount=%d) Sleeping...\n", gpLayerState->GetRefCount()));
        gpLayerState->Unlock ();
        Sleep (200);
        gpLayerState->Lock ();

⌨️ 快捷键说明

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