📄 btsdp.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
BTSDP.H
Abstract:
This module contains the BTh SDP structures.
Doron Holan
Notes:
Environment:
Kernel mode only
Revision History:
*/
#ifndef __BTSDP_H__
#define __BTSDP_H__
///////////////////////////////////////////////////////
// typedefs
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// Defines
//////////////////////////////////////////////////////
//
// PDU ID
//
#define SdpPDU_Error 1
#define SdpPDU_ServiceSearchRequest 2
#define SdpPDU_ServiceSearchResponse 3
#define SdpPDU_ServiceAttributeRequest 4
#define SdpPDU_ServiceAttributeResponse 5
#define SdpPDU_ServiceSearchAttributeRequest 6
#define SdpPDU_ServiceSearchAttributeResponse 7
//
// Values used for the L2CAP configuration process
//
#define SDP_MTU 672
#define SDP_QOS 0x01
#define SDP_FLUSH_TIMEOUT 0xffff // best effort
///////////////////////////////////////////////////////
// structures
/////////////////////////////////////////////////////
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
typedef struct _SdpServiceSearch {
unsigned short cid; // in
SdpQueryUuid *uuids; // in
unsigned short cUUIDs; // in (max 12)
unsigned short cMaxHandles; // in
} SdpServiceSearch;
typedef struct _SdpAttributeSearch {
unsigned short cid; // in
unsigned long recordHandle; // in
SdpAttributeRange *range; // in
unsigned long numAttributes; // in
} SdpAttributeSearch;
typedef struct _SdpServiceAttributeSearch {
unsigned short cid; // in
SdpQueryUuid *uuids; // in
unsigned short cUUIDs; // in
SdpAttributeRange *range; // in
unsigned long numAttributes; // in
} SdpServiceAttributeSearch;
#endif
////////////////////////////////////////////////
// Main SDP interface structure
///////////////////////////////////////////////
#include <pshpack1.h>
struct SdpPDU {
UCHAR pduId;
USHORT transactionId;
USHORT parameterLength;
PVOID Read(PVOID pBuffer);
PUCHAR Write(PUCHAR pBuffer);
};
struct ContinuationState {
ContinuationState() { ZERO_THIS(); }
ContinuationState(PVOID p) { ZERO_THIS(); Init(p); }
void Init(PVOID p);
inline UCHAR GetTotalSize() { return sizeof(size) + size; }
BOOLEAN Read (UCHAR *pStream, ULONG streamSize);
void Write(UCHAR *pStream);
inline ULONG IsEqual(const ContinuationState& rhs) {
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
return (rhs.size == size) &&
(RtlCompareMemory(rhs.state, state, size) == size);
#else
return (rhs.size == size) &&
(memcmp(rhs.state, state, size) == 0);
#endif
}
UCHAR size;
UCHAR state[16];
};
#include <poppack.h>
enum SdpChannelState{
SdpChannelStateConnecting = 0,
SdpChannelStateOpen,
SdpChannelStateClosing,
SdpChannelStateClosed,
};
enum ConnectionAcquireReason {
AcquireCreate = 0x100,
AcquireConfigInd,
AcquireConnectInd,
AcquireConnect,
};
#define REASON(r) ((PVOID) r)
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
struct FileObjectEntry {
SELF_DESTRUCT
FileObjectEntry(PFILE_OBJECT pFO) : pFileObject(pFO) { InitializeListHead(&entry); }
LIST_ENTRY entry;
PFILE_OBJECT pFileObject;
};
#endif
struct SdpConnection{
#if defined (UNDER_CE) || defined (WINCE_EMULATION)
void *pCallContext; // points to (Call *) in sdpbase.cxx, back pointer
NTSTATUS ReadAsync(BOOLEAN shortOk = TRUE) { return STATUS_SUCCESS; }
// PVOID ReleaseeAndIdle(PVOID tag) { ; }
NTSTATUS SdpConnection::ReadWorkItemWorker(PUCHAR pResponse, USHORT usSize);
ULONG SendOrQueueRequest(void);
unsigned long SendInitialRequestToServer(void);
ULONG ConnInformation; // forges pRequestorIrp->IoStatus.Information
PUCHAR pClientBuf;
ULONG cClientBuf;
#if defined (DEBUG) || defined (_DEBUG)
BOOL fClientNotified;
#endif
#endif
SELF_DESTRUCT
SdpConnection(BThDevice *pDev, BOOLEAN isClient);
~SdpConnection();
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
//
// Initial setup
//
BOOLEAN Init();
NTSTATUS Config(USHORT mtu, USHORT *pApprovedMtu);
BOOLEAN InMtuDone(USHORT psm);
BOOLEAN OutMtuDone(USHORT psm);
BOOLEAN FinalizeConnection();
void CompletePendingConnectRequests(NTSTATUS Status);
//
// raw I/O wrappers
//
BOOLEAN SetupReadBuffer();
NTSTATUS ReadAsync(BOOLEAN shortOk = TRUE);
static NTSTATUS _ReadAsyncCompletion(PDEVICE_OBJECT pDeviceObject,PIRP pIrp, PVOID pContext);
void ReadAsyncComplete();
static void _ReadWorkItemCallback(IN PVOID Parameter);
void ReadWorkItemWorker();
#endif
NTSTATUS Write(PVOID pBuffer, ULONG length);
NTSTATUS WriteSdpError(USHORT transactionId, SDP_ERROR sdpErrorValue);
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
static NTSTATUS _TimeoutDisconnectComplete(PDEVICE_OBJECT pDeviceObject,PIRP pIrp, PVOID pContext);
//
// State management
//
void LockState(KIRQL *pIrql) { KeAcquireSpinLock(&stateSpinLock, pIrql); }
void UnlockState(KIRQL irql) { KeReleaseSpinLock(&stateSpinLock, irql); }
//
// For I/O related requests
//
NTSTATUS Acquire(PVOID tag = NULL) { return IoAcquireRemoveLock(&remLock, tag); }
void Release(PVOID tag = NULL) { IoReleaseRemoveLock(&remLock, tag); }
void ReleaseAndWait();
void ReleaseAndProcessNextRequest(PIRP pIrp);
//
// File object maintance
//
BOOLEAN AddFileObject(PFILE_OBJECT pFileObject);
FileObjectEntry * FindFileObject(PFILE_OBJECT pFileObject);
LONG RemoveFileObject(PFILE_OBJECT pFileObject);
LONG RemoveFileObject(FileObjectEntry *pEntry);
void Cleanup(PFILE_OBJECT pFileObject);
#else
void ReleaseAndProcessNextRequest(PIRP pIrp) { ; }
#endif
void FireWmiEvent(SDP_SERVER_LOG_TYPE Type, PVOID Buffer, ULONG Length) { ; }
void FireWmiEvent(SDP_SERVER_LOG_TYPE Type, const BD_ADDR& Address, USHORT Mtu) { ; }
NTSTATUS SendServiceSearchRequest(PIRP pIrp, SdpServiceSearch *pSearch);
NTSTATUS SendAttributeSearchRequest(PIRP pIrp, SdpAttributeSearch *pSearch);
NTSTATUS SendServiceSearchAttributeRequest(PIRP pIrp, SdpServiceAttributeSearch *pSearch);
//
// Send out a request to the server
//
NTSTATUS SendInitialRequestToServer(PIRP pClientIrp,
PVOID pRequest,
USHORT requestLength,
UCHAR pduId);
//
// Ask for more from the server
//
NTSTATUS SendContinuationRequestToServer(ContinuationState *pContState);
//
// Handle what the server sent back in a response to this client
//
NTSTATUS OnServiceSearchResponse(SdpPDU *pPdu, PUCHAR pBuffer, ULONG_PTR* pInfo);
NTSTATUS OnServiceAttributeResponse(SdpPDU *pPdu, PUCHAR pBuffer, ULONG_PTR* pInfo);
NTSTATUS OnServiceSearchAttributeResponse(SdpPDU *pPdu, PUCHAR pBuffer, ULONG_PTR* pInfo);
//
// Handle what the client is requesting from this server
//
NTSTATUS OnServiceSearchRequest(SdpPDU *pPdu,
PUCHAR pBuffer,
PSDP_ERROR pSdpError);
NTSTATUS OnServiceAttributeRequest(SdpPDU *pPdu,
PUCHAR pBuffer,
PSDP_ERROR pSdpError);
NTSTATUS OnServiceSearchAttributeRequest(SdpPDU *pPdu,
PUCHAR pBuffer,
PSDP_ERROR pSdpError);
//
// Clear out the cached query
//
void FlushClientRequestCache(NTSTATUS status);
//
// Check to see if the current request matches the request we just cached.
// If so, and there is ample room, complete
NTSTATUS IsPreviousRequest(PIRP pIrp,
UCHAR pduId,
SdpQueryUuid *pUuid,
SdpAttributeRange *pRange,
ULONG numRange,
ULONG_PTR* pInfo);
//
// Server side
//
NTSTATUS SaveQueryInfo(SdpPDU *pPdu, PVOID pQuery, PSDP_ERROR pSdpError);
void SendResponseToClient(SdpPDU *pPdu,
UCHAR pduId,
PUCHAR pResponse,
ULONG responseSize);
NTSTATUS SendResponseToClient(NTSTATUS createPduStatus,
const ContinuationState& cs,
SdpPDU *pPdu,
PUCHAR pClientRequest,
PUCHAR pResponse,
ULONG responseSize,
UCHAR pduId,
PSDP_ERROR pSdpError);
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
BOOL IsClient();
BOOL IsServer();
#else
BOOLEAN IsClient() { return client; }
BOOLEAN IsServer() { return !client; }
BOOLEAN Disconnect(SdpChannelState *pPreviousState = NULL);
//
// Lock to guard I/O so we don't delete the object before all I/O completes
//
IO_REMOVE_LOCK remLock;
//
// Number of creates for this connection and a list of each file object for
// each create (to tear down connections on close if the user fails to do so)
//
LONG createCount;
CList<FileObjectEntry, FIELD_OFFSET(FileObjectEntry, entry)> fileObjectList;
//
// List of pending connect irps waiting on the real l2cap connection
// completing. This list is guarded by SdpConnection::LockState
//
CList<IRP, IRP_LE_OFFSET> connectList;
//
// Link into the SdpInterface list of connections
//
LIST_ENTRY entry;
//
// Link into the timer list of connections
//
LIST_ENTRY timerEntry;
LONG timeoutTime, maxTimeout;
//
// Spinlock to guard the state of the object and associated state variables
//
KSPIN_LOCK stateSpinLock;
SdpChannelState channelState;
ULONG configRetry;
BOOLEAN configInDone, configOutDone, client, closing;
//
// We one read and write request which are sent down to the bus so we do not
// have to worry about allocating them every time. We also have a read buffer
// preallocated for the same reason.
//
// Every time a read completes, queue a work item and process the results at
// PASSIVE
//
PIRP pWriteIrp, pReadIrp;
PBRB pReadBrb;
PVOID pReadBuffer;
WORK_QUEUE_ITEM readWorkItem;
//
// BTHPORT provided value, used for BRBs
//
PVOID hConnection;
//
// Address of the device we are talking to
//
BD_ADDR btAddress;
//
// The BTHPORT object for this radio
BThDevice *pDevice;
//
// The client's request in IRP form. It does not have a cancel routine set
// even though it has been pended. I do this b/c if I complete the cancelled
// irp before I receive a server response, the client will not know when he
// can send another request.
//
PIRP pRequestorIrp;
#endif
//
// The next transactionId we will use
//
USHORT transactionId;
USHORT inMtu, outMtu;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -