Exemplo n.º 1
0
__drv_sameIRQL
NTSTATUS
BthEchoCliOpenRemoteConnection(
    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx,
    __in WDFFILEOBJECT FileObject,
    __in WDFREQUEST Request
    )
/*++

Description:

    This routine is invoked by BthEchoCliEvtDeviceFileCreate.
    In this routine we send down open channel BRB.

    This routine allocates open channel BRB. If the request
    is sent down successfully completion routine needs to free
    this BRB.
    
Arguments:

    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx - 
    __in WDFFILEOBJECT FileObject - 
    __in WDFREQUEST Request - 

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status;
    WDFOBJECT connectionObject;    
    struct _BRB_L2CA_OPEN_CHANNEL *brb = NULL;
    PBTHECHO_CONNECTION connection = NULL;
    PBTHECHOSAMPLE_CLIENT_FILE_CONTEXT fileCtx = GetFileContext(FileObject);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, 
        "Connect request");        

    //
    // Create the connection object that would store information
    // about the open channel
    //
    // Set file object as the parent for this connection object
    //
    status = BthEchoConnectionObjectCreate(
        &DevCtx->Header,
        FileObject, //parent
        &connectionObject
        );

    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    connection = GetConnectionObjectContext(connectionObject);

    connection->ConnectionState = ConnectionStateConnecting;

    //
    // Get the BRB from request context and initialize it as
    // BRB_L2CA_OPEN_CHANNEL BRB
    //
    brb = (struct _BRB_L2CA_OPEN_CHANNEL *)GetRequestContext(Request);

    DevCtx->Header.ProfileDrvInterface.BthReuseBrb(
        (PBRB)brb, 
        BRB_L2CA_OPEN_CHANNEL
        );
    
    brb->Hdr.ClientContext[0] = connection;
    brb->BtAddress = DevCtx->ServerBthAddress;
    brb->Psm = fileCtx->ServerPsm;

    brb->ChannelFlags = CF_ROLE_EITHER;

    brb->ConfigOut.Flags = 0;
    brb->ConfigIn.Flags = 0;

    brb->ConfigOut.Flags |= CFG_MTU;
    brb->ConfigOut.Mtu.Max = L2CAP_DEFAULT_MTU;
    brb->ConfigOut.Mtu.Min = L2CAP_MIN_MTU;
    brb->ConfigOut.Mtu.Preferred = L2CAP_DEFAULT_MTU;

    brb->ConfigIn.Flags = CFG_MTU;
    brb->ConfigIn.Mtu.Max = brb->ConfigOut.Mtu.Max;
    brb->ConfigIn.Mtu.Min = brb->ConfigOut.Mtu.Min;
    brb->ConfigIn.Mtu.Preferred = brb->ConfigOut.Mtu.Max;

    //
    // Get notificaiton about remote disconnect 
    //
    brb->CallbackFlags = CALLBACK_DISCONNECT;                                                   

    brb->Callback = &BthEchoCliIndicationCallback;
    brb->CallbackContext = connection;
    brb->ReferenceObject = (PVOID) WdfDeviceWdmGetDeviceObject(DevCtx->Header.Device);
    brb->IncomingQueueDepth = 50;

    status = BthEchoSharedSendBrbAsync(
        DevCtx->Header.IoTarget,
        Request,
        (PBRB) brb,
        sizeof(*brb),
        BthEchoCliRemoteConnectCompletion,
        brb    //Context
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONNECT, 
            "Sending brb for opening connection failed, returning status code %!STATUS!\n", status);

        goto exit;
    }            

exit:

    if(!NT_SUCCESS(status))
    {
        if (connection)
        {
            //
            // Set the right state to facilitate debugging
            //
            connection->ConnectionState = ConnectionStateConnectFailed;            
        }

        //
        // In case of failure of this routine we will fail
        // Create which will delete file object and since connection object
        // is child of the file object, it will be deleted too
        //
    }
    
    return status;
}
Exemplo n.º 2
0
BOOLEAN
BthEchoConnectionObjectRemoteDisconnect(
    _In_ PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER DevCtxHdr,
    _In_ PBTHECHO_CONNECTION Connection
    )
/*++

Description:

    This routine sends a disconnect BRB for the connection

Arguments:

    DevCtxHdr - Device context header
    Connection - Connection which is to be disconnected

Return Value:

    TRUE is this call initiates the disconnect.
    FALSE if the connection was already disconnected.

--*/
{
    struct _BRB_L2CA_CLOSE_CHANNEL * disconnectBrb;

    //
    // Cancel continuous readers for the connection
    //
    BthEchoConnectionObjectContinuousReaderCancelReaders(Connection);
    
    WdfSpinLockAcquire(Connection->ConnectionLock);
    
    if (Connection->ConnectionState == ConnectionStateConnecting) 
    {
        //
        // If the connection is not completed yet set the state 
        // to disconnecting.
        // In such case we should send CLOSE_CHANNEL Brb down after 
        // we receive connect completion.
        //
        
        Connection->ConnectionState = ConnectionStateDisconnecting;

        //
        // Clear event to indicate that we are in disconnecting
        // state. It will be set when disconnect is completed
        //
        KeClearEvent(&Connection->DisconnectEvent);

        WdfSpinLockRelease(Connection->ConnectionLock);
        return TRUE;

    } 
    else if (Connection->ConnectionState != ConnectionStateConnected)
    {
        //
        // Do nothing if we are not connected
        //

        WdfSpinLockRelease(Connection->ConnectionLock);
        return FALSE;
    }

    Connection->ConnectionState = ConnectionStateDisconnecting;
    WdfSpinLockRelease(Connection->ConnectionLock);

    //
    // We are now sending the disconnect, so clear the event.
    //

    KeClearEvent(&Connection->DisconnectEvent);

    DevCtxHdr->ProfileDrvInterface.BthReuseBrb(&Connection->ConnectDisconnectBrb, BRB_L2CA_CLOSE_CHANNEL);

    disconnectBrb = (struct _BRB_L2CA_CLOSE_CHANNEL *) &(Connection->ConnectDisconnectBrb);
    
    disconnectBrb->BtAddress = Connection->RemoteAddress;
    disconnectBrb->ChannelHandle = Connection->ChannelHandle;

    //
    // The BRB can fail with STATUS_DEVICE_DISCONNECT if the device is already
    // disconnected, hence we don't assert for success
    //

    (void) BthEchoSharedSendBrbAsync(
        DevCtxHdr->IoTarget, 
        Connection->ConnectDisconnectRequest, 
        (PBRB) disconnectBrb,
        sizeof(*disconnectBrb),
        BthEchoConnectionObjectDisconnectCompletion,
        Connection
        );    

    return TRUE;
}