NTSTATUS BthEchoSrvConnectionStateConnected( WDFOBJECT ConnectionObject ) /*++ Routine Description: This routine is invoked by BthEchoSrvRemoteConnectResponseCompletion when connect response is completed. We initialize and submit continous readers in this routine. Arguments: ConnectionObject - Connection object for which connect response completed --*/ { PBTHECHO_CONNECTION connection; NTSTATUS status; connection = GetConnectionObjectContext(ConnectionObject); status = BthEchoConnectionObjectInitializeContinuousReader( connection, BthEchoSrvConnectionObjectContReaderReadCompletedCallback, BthEchoSrvConnectionObjectContReaderFailedCallback, BthEchoSampleMaxDataLength ); if (!NT_SUCCESS(status)) { goto exit; } status = BthEchoConnectionObjectContinuousReaderSubmitReaders( connection ); if (!NT_SUCCESS(status)) { goto exit; } exit: return status; }
_Use_decl_annotations_ VOID BthEchoEvtConnectionObjectCleanup( WDFOBJECT ConnectionObject ) /*++ Description: This routine is invoked by the Framework when connection object gets deleted (either explicitly or implicitly because of parent deletion). Since we mark ExecutionLevel as passive for connection object we get this callback at passive level and can wait for stopping of continuous readers and for disconnect to complete. Arguments: ConnectionObject - The Connection Object Return Value: None --*/ { PBTHECHO_CONNECTION connection = GetConnectionObjectContext(ConnectionObject); PAGED_CODE(); BthEchoConnectionObjectWaitForAndUninitializeContinuousReader(connection); KeWaitForSingleObject(&connection->DisconnectEvent, Executive, KernelMode, FALSE, NULL); WdfObjectDelete(connection->ConnectDisconnectRequest); }
__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; }
NTSTATUS BthEchoConnectionObjectInit( _In_ WDFOBJECT ConnectionObject, _In_ PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER DevCtxHdr ) /*++ Description: This routine initializes connection object. It is invoked by BthEchoConnectionObjectCreate. Arguments: ConnectionObject - Object to initialize DevCtxHdr - Device context header Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; PBTHECHO_CONNECTION connection = GetConnectionObjectContext(ConnectionObject); connection->DevCtxHdr = DevCtxHdr; connection->ConnectionState = ConnectionStateInitialized; // // Initialize spinlock // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ConnectionObject; status = WdfSpinLockCreate( &attributes, &connection->ConnectionLock ); if (!NT_SUCCESS(status)) { goto exit; } // // Create connect/disconnect request // status = WdfRequestCreate( &attributes, DevCtxHdr->IoTarget, &connection->ConnectDisconnectRequest ); if (!NT_SUCCESS(status)) { return status; } // // Initialize event // KeInitializeEvent(&connection->DisconnectEvent, NotificationEvent, TRUE); // // Initalize list entry // InitializeListHead(&connection->ConnectionListEntry); connection->ConnectionState = ConnectionStateInitialized; exit: return status; }