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

📄 bthsco.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    }

    Link *pLink = gpLayerState->pLinks;

    while (gpLayerState->pLinks) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: Deleting link 0x%04x\n", gpLayerState->pLinks->hScoConnection));

        Link *pNext = gpLayerState->pLinks->pNext;
        delete gpLayerState->pLinks;
        gpLayerState->pLinks = pNext;
    }

    Call *pC = gpLayerState->pCalls;
    gpLayerState->pCalls = NULL;

    while (pC) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: signalling call 0x%08x\n", pC));

        Call *pNext = pC->pNext;
        pC->pNext = NULL;
        pC->pPrev = NULL;

        CallSignal (pC, ERROR_SHUTDOWN_IN_PROGRESS);
        pC = pNext;
    }

    if (gpLayerState->hHCI) {
        SVSUTIL_ASSERT(gpfHCI_CloseDeviceContext);
        gpfHCI_CloseDeviceContext (gpLayerState->hHCI);
    }
    gpLayerState->Zero();

    gpLayerState->Unlock();

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

int sco_Bind(void *pUserData, SCO_CALLBACKS *pCallbacks, SCO_INTERFACE *pInterface)
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Bind\n"));

    if (!pCallbacks || !pInterface) {
        return ERROR_INVALID_PARAMETER;
    }

    gpLayerState->Lock ();

    if (!gpLayerState->fIsRunning) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Bind :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
        gpLayerState->Unlock();
        return ERROR_SHUTDOWN_IN_PROGRESS;
    }

    if (gpLayerState->fIsBinded) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_Bind :: ERROR_ALREADY_INITIALIZED\n"));
        return ERROR_ALREADY_INITIALIZED;
    }

    pInterface->Call            = sco_Call_In;
    pInterface->AbortCall       = sco_AbortUserCall_In;
    pInterface->DataPacketDown  = sco_DataPacketDown_In;

    memcpy(&gpLayerState->sco_callbacks, pCallbacks, sizeof(SCO_CALLBACKS));

    gpLayerState->pUserData = pUserData;
    gpLayerState->fIsBinded = TRUE;

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Bind :: return ERROR_SUCCESS\n"));
    gpLayerState->Unlock ();
    return ERROR_SUCCESS;
}

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

    gpLayerState->Lock ();

    if (!gpLayerState->fIsBinded) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_Unbind :: ERROR_SERVICE_NOT_ACTIVE\n"));
        gpLayerState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    //
    // abort all current Calls
    //

    Call *pCall = gpLayerState->pCalls;
    gpLayerState->pCalls = NULL;
    while (pCall)
    {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_Unbind :: aborting call %#x\n", pCall));
        Call *pNext = pCall->pNext;

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

        if (pCall->fInvokedHCI) {
            //
            // inform HCI that the call is being aborted
            // the gpLayerState->pCalls already been NULLed so the sco_CallAborted_Out
            // callback won't do anything useful
            //

            BT_LAYER_ABORT_CALL pFunction = gpLayerState->hci_if.hci_AbortCall;
            HANDLE hHCI = gpLayerState->hHCI;

            int iRes = ERROR_INTERNAL_ERROR;

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

            __try {
                iRes = pFunction (hHCI, pCall);
            } __except (1) {
                IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_AbortCall :: exception in hci_AbortCall\n"));
            }

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

        CallSignal(pCall, ERROR_OPERATION_ABORTED);
        pCall = pNext;
    }

    //
    // abort all Links
    //

    Link *pLink = gpLayerState->pLinks;
    gpLayerState->pLinks = NULL;
    while (pLink)
    {
        Link   *pNextLink = pLink->pNext;
        USHORT  hSco      = pLink->hScoConnection;
        USHORT  hAcl      = pLink->hAclConnection;

        int iRes = ERROR_INTERNAL_ERROR;

        if (gpLayerState->fIsRunning && gpLayerState->fConnected) {
            IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Unbind :: disconnecting Link=%#x, hSco=%#x, hAcl=%#x\n", pLink, hSco, hAcl));

            HCI_Disconnect_In pFunction = gpLayerState->hci_if.hci_Disconnect_In;
            HANDLE hHCI = gpLayerState->hHCI;

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

            __try {
                iRes = pFunction (hHCI, NULL, hSco, BT_ERROR_OETC_USER_ENDED);
            } __except (1) {
                IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_Unbind %#x :: exception in hci_Disconnect_In\n", pLink));
            }

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

        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Unbind :: deleting Link=%#x, hSco=%#x, hAcl=%#x\n", pLink, hSco, hAcl));
        delete pLink;
        pLink = pNextLink;
    }


    memset(&gpLayerState->sco_callbacks, 0, sizeof(SCO_CALLBACKS));
    gpLayerState->pUserData = NULL;
    gpLayerState->fIsBinded = FALSE;

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_Unbind :: return ERROR_SUCCESS\n"));
    gpLayerState->Unlock ();
    return ERROR_SUCCESS;
}


////////////////////////////////////////////
// stack notification routines
// note: they are executed asynchronously (a thread is created for them)
//       (they do not execute on same thread as HCI callback)
//
//  StackInitDevice
//  StackNotifyUser
// The following 3 routines are ThreadProcs [see function sco_Stack_Event]
//  StackDisconnect
//  StackDown
//  StackUp
////////////////////////////////////////////

// helper function
static int SetSCOFlowControl(BOOL bEnable)
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: SetSCOFlowControl(%s)\n", bEnable ? L"TRUE" : L"FALSE"));

    SVSUTIL_ASSERT(gpLayerState);
    SVSUTIL_ASSERT(gpLayerState->IsLocked());

    if (!gpLayerState->fIsRunning) {
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    Call *pCall = CallCreateNew (CALL_TYPE_WRITE_SCO_FLOW_CONTROL, TRUE, NULL);
    if (!pCall) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: SetSCOFlowControl :: ERROR_OUTOFMEMORY\n"));
        return ERROR_OUTOFMEMORY;
    }
    CallInsert(pCall);

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: SetSCOFlowControl :: created call 0x%08x\n", pCall));

    HCI_WriteSCOFlowControlEnable_In pFunction = gpLayerState->hci_if.hci_WriteSCOFlowControlEnable_In;
    HANDLE hHCI = gpLayerState->hHCI;

    int iRes = ERROR_INTERNAL_ERROR;

    pCall->fInvokedHCI = TRUE;

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

    __try {
        iRes = pFunction (hHCI, pCall, bEnable ? TRUE : FALSE);
    } __except (1) {
        IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: SetSCOFlowControl :: exception in hci_WriteSCOFlowControlEnable_In\n"));
    }

    if (iRes) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: SetSCOFlowControl :: hci_WriteSCOFlowControlEnable_In failed with %d\n", iRes));

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

        if (CallVerify(pCall, CALL_TYPE_WRITE_SCO_FLOW_CONTROL)) {
            CallRemove(pCall);
            CallSignal(pCall, iRes);
        }
        return iRes;
    }

    // wait for completion
    int iResult;
    DWORD dwWait = WaitForSingleObject(pCall->hEvent, 5000);

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

    if (WAIT_OBJECT_0 == dwWait) {
	    iResult = pCall->iResult;
	    CallDelete(pCall);
	}
	else {
		iResult = ERROR_TIMEOUT;
        CallRemove(pCall);
        CallDelete(pCall);
	}

    if (!gpLayerState->fIsRunning) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: SetSCOFlowControl :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
        return ERROR_SHUTDOWN_IN_PROGRESS;
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: SetSCOFlowControl returning %#x\n", iResult));
    return iResult;
}

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

    gpLayerState->Lock ();

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

    if (ERROR_SUCCESS != SetSCOFlowControl(TRUE)) {
    	// It is ok if this fails.  We have flow control in HCI.
    	IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Failed to set SCO flow control.\n"));
    }

    gpLayerState->Unlock();

    return ERROR_SUCCESS;
}

static int StackNotifyUser(int iEvent)
{
    if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}

    gpLayerState->Lock();

    SCO_CALLBACK_StackEvent pCallBack = gpLayerState->sco_callbacks.StackEvent;
    if (pCallBack) {

        int iRes = ERROR_INTERNAL_ERROR;
        void *pUserData = gpLayerState->pUserData;

        gpLayerState->AddRef ();
        gpLayerState->Unlock ();
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: StackNotifyUser :: going into callback\n"));

        __try {
            iRes = pCallBack (pUserData, iEvent);
        } __except (1) {
            IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: StackNotifyUser :: exception in callback\n"));
        }

        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: StackNotifyUser :: came from callback\n"));
        gpLayerState->Lock  ();
        gpLayerState->DelRef ();
    }

    gpLayerState->Unlock();
    return ERROR_SUCCESS;
}

static DWORD WINAPI StackDisconnect (LPVOID lpVoid) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Disconnecting stack\n"));

    StackNotifyUser(BTH_STACK_DISCONNECT);

    sco_CloseDriverInstance();
    sco_UninitializeOnce();

    return ERROR_SUCCESS;
}

static DWORD WINAPI StackDown (LPVOID lpVoid) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    StackNotifyUser(BTH_STACK_DOWN);

	// gpLayerState may be disconnecting, in which case StackDown does not need 
	// to do anything.
	if(WaitForSingleObject(gpLayerState->hClosingEvent, 0) != WAIT_TIMEOUT) {
		return 0;
	}

    gpLayerState->Lock ();

    if ((! gpLayerState->fIsRunning) || (! gpLayerState->fConnected)) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack Down received :: already down\n"));

        gpLayerState->Unlock ();

        return ERROR_SERVICE_NOT_ACTIVE;
    }

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack Down :: taking down\n"));

    gpLayerState->fConnected = FALSE;


    Link *pLink = gpLayerState->pLinks;

    while (gpLayerState->pLinks) {
        Link *pNext = gpLayerState->pLinks->pNext;
        delete gpLayerState->pLinks;
        gpLayerState->pLinks = pNext;
    }


    Call *pC = gpLayerState->pCalls;

    while (pC) {
        CallRemove (pC);
        CallSignal (pC, ERROR_SHUTDOWN_IN_PROGRESS);

        pC = gpLayerState->pCalls;

⌨️ 快捷键说明

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