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

📄 bthsco.cxx

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

    int iRet = ERROR_SUCCESS;
    int iResult = StatusToError(status, ERROR_PROTOCOL_UNREACHABLE);

    if (status == 0) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: creating link\n"));

        Link *pLink = new Link;
        if (pLink) {
            pLink->b = *pba;
            pLink->hScoConnection = connection_handle;
            pLink->hAclConnection = pCall->uParameters.Connect.hAclConnection;
            pLink->pNext = gpLayerState->pLinks;
            gpLayerState->pLinks = pLink;
        } else {
            IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_ConnectionComplete_Event ERROR_OUTOFMEMORY\n"));
            iResult = ERROR_OUTOFMEMORY;
            iRet = ERROR_OUTOFMEMORY;
        }
    }

    // set params
    if (pCall->fCallType == CALL_TYPE_CONNECT) {
        pCall->uParameters.Connect.hScoConnection = connection_handle;
    } else if (pCall->fCallType == CALL_TYPE_ACCEPT_INCOMING_CONNECTION) {
        pCall->uParameters.AcceptIncomingConnection.Address = *pba;
        pCall->uParameters.AcceptIncomingConnection.hScoConnection = connection_handle;
    } else {
        SVSUTIL_ASSERT(!"wrong fCallType!");
        iResult = ERROR_INTERNAL_ERROR;
        iRet = ERROR_INTERNAL_ERROR;
    }

    // finish the call
    CallRemove (pCall);
    CallSignal (pCall, iResult);

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

    gpLayerState->Unlock ();

    return iRet;
}

static int sco_DisconnectionComplete_Event (void            *pUserContext, 
                                           void             *pCallContext, 
                                           unsigned char    status, 
                                           unsigned short   connection_handle, 
                                           unsigned char    reason) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}

    gpLayerState->Lock ();
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: call 0x%08x, status 0x%02x handle 0x%04x reason %#x\n", pCallContext, status, connection_handle, reason));

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

    if (status == 0) {
        Link *pLink = gpLayerState->pLinks;
        Link *pParent = NULL;

        // find the link
        while (pLink) {
            if (pLink->hScoConnection == connection_handle)
                break;
            pParent = pLink;
            pLink = pLink->pNext;
        }

        if (pLink) {
            IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: deleting Link h=0x%04x\n", connection_handle));

            if (pParent)
                pParent->pNext = pLink->pNext;
            else
                gpLayerState->pLinks = pLink->pNext;

            delete pLink;

           	StackNotifyUser(SCO_LINK_DISCONNECT);           	
        } else {
            IFDBG(DebugOut (DEBUG_WARN, L"SCO :: sco_DisconnectionComplete_Event :: h=0x%04x not found\n", connection_handle));
        }
    } else {
        IFDBG(DebugOut (DEBUG_WARN, L"SCO :: sco_DisconnectionComplete_Event :: h=0x%04x status=%d\n", connection_handle, status));
    }

    Call *pCall = CallVerify ((Call*)pCallContext, CALL_TYPE_DISCONNECT);
    if (! pCall) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: no context\n"));
        gpLayerState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    // finish the call
    CallRemove (pCall);
    CallSignal (pCall, StatusToError(status, ERROR_PROTOCOL_UNREACHABLE));

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

    gpLayerState->Unlock ();

    return ERROR_SUCCESS;
}

static int sco_ConnectionRequest_Event (void            *pUserContext,
                                        void            *pCallContext, // NULL
                                        BD_ADDR         *pba,
                                        unsigned int    class_of_device,
                                        unsigned char   link_type) 
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}
	
    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: pCallContext=%#x, addr=%04x%08x, class_of_device=%#x, link_type=%#x\n",
        pCallContext, pba->NAP, pba->SAP, class_of_device, link_type));

    if (link_type != BT_LINK_TYPE_SCO) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: non-SCO link type recved\n"));
        return ERROR_PROTOCOL_UNREACHABLE;
    }

    gpLayerState->Lock ();

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

    //
    // NOTE NOTE NOTE NOTE NOTE
    //  CallInsert() inserts into the head of the list.
    //  We must find the LAST Call on the list that meets the address filter requirements
    //  so that the first person who called sco_RecvConnection is the first one to be released
    //
    Call *pCall = NULL;
    Call *pProbe = gpLayerState->pCalls;
    while (pProbe)
    {
        if (pProbe->fCallType == CALL_TYPE_WAIT_FOR_INCOMING_CONNECTION) {
            if (    (pProbe->uParameters.WaitIncomingConnection.bAllAddresses)
                ||  (pProbe->uParameters.WaitIncomingConnection.Address == *pba)) {
                pCall = pProbe;
            }
        }
        pProbe = pProbe->pNext;
    }

    if (pCall) {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event %#x :: accepting connection\n", pCall));

        pCall->fCallType = CALL_TYPE_ACCEPT_INCOMING_CONNECTION;
        pCall->fInvokedHCI = TRUE;

        HCI_AcceptConnectionRequest_In pFunction = gpLayerState->hci_if.hci_AcceptConnectionRequest_In;
        HANDLE hHCI = gpLayerState->hHCI;

        int iRes = ERROR_INTERNAL_ERROR;

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

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

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

        if (iRes) {
            IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: hci_AcceptConnectionRequest_In failed %d\n", iRes));
            if (CallVerify(pCall, CALL_TYPE_ACCEPT_INCOMING_CONNECTION)) {
                CallRemove(pCall);
                CallSignal(pCall, iRes);
            }
            gpLayerState->Unlock();
            return iRes;
        }

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

    } else {
        IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: rejecting connection (no context)\n"));

        HCI_RejectConnectionRequest_In pFunction = gpLayerState->hci_if.hci_RejectConnectionRequest_In;
        HANDLE hHCI = gpLayerState->hHCI;

        int iRes = ERROR_INTERNAL_ERROR;

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

        __try {
            iRes = pFunction (hHCI, NULL, pba, BT_ERROR_HOST_REJECTED_LIMITED_RESOURCES);
        } __except (1) {
            IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_ConnectionRequest_Event :: exception in hci_RejectConnectionRequest_In\n"));
        }

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

        if (iRes) {
            IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: hci_RejectConnectionRequest_In failed %d\n", iRes));
            gpLayerState->Unlock();
            return iRes;
        }

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


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

static int sco_NumberOfCompletedPackets_Event (void             *pUserContext, 
                                               void             *pCallContext, 
                                               unsigned short   connection_handle, 
                                               unsigned short   num_of_completed_packets)
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}

    IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: pCallContext=%#x, handle=%#x, num_completed=%d",
        pCallContext, connection_handle, num_of_completed_packets));

    gpLayerState->Lock ();

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

    SCO_CALLBACK_PacketsCompleted pCallBack = gpLayerState->sco_callbacks.PacketsCompleted;
    if (pCallBack) {

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

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

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

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

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

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

static int sco_DataPacketUp_Event(void *pUserContext, unsigned short connection_handle,  BD_BUFFER *pBuffer)
{
	if (! gpLayerState) {
		return ERROR_SERVICE_NOT_ACTIVE;
	}

    IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketUp_Event :: handle=%#x, bd_buffer=%#x", connection_handle, pBuffer));

    gpLayerState->Lock ();

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

    SCO_CALLBACK_DataPacketUp pCallBack = gpLayerState->sco_callbacks.DataPacketUp;
    if (pCallBack) {

        int     iRes            = ERROR_INTERNAL_ERROR;
        void    *pUserData      = gpLayerState->pUserData;
        PUCHAR  pDataBuffer     = &pBuffer->pBuffer[pBuffer->cStart];
        DWORD   dwDataBufferLen = pBuffer->cEnd - pBuffer->cStart;

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

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

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

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

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


///////////////////////////////////////////////////////////
// Interface functions
///////////////////////////////////////////////////////////

static int sco_AbortCall(Call *pCall, BOOL bHciAbort)
{
	if (!gpLayerState) {
        return ERROR_SERVICE_DOES_NOT_EXIST;
    }
	
    SVSUTIL_ASSERT(pCall);
    SVSUTIL_ASSERT(gpLayerState->IsLocked());

    if (!pCall) {
        return ERROR_INVALID_PARAMETER;
    } else if (!gpLayerState) {
        return ERROR_SHUTDOWN_IN_PROGRESS;
    } else if (!gpLayerState->IsLocked()) {
        return ERROR_NOT_LOCKED;
    }

    if (bHciAbort) {
        //
        // HCI was invoked using this pCall, so tell HCI to abort that call.
        // invoke hci_AbortCall.
        // This will induce a sco_CallAborted_Out callback
        //

        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 ();

    } else {
        //
        // HCI has not been invoked using this pCall so remove it from pCalls and signal it
        //
        CallRemove(pCall);
        CallSignal(pCall, ERROR_OPERATION_ABORTED);
    }

    return ERROR_SUCCESS;
}

static int sco_AbortUserCall_In (SCO_USER_CALL* pUserCall)
{
	if (!gpLayerState) {
 

⌨️ 快捷键说明

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