📄 rfcomm.cxx
字号:
//
// 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.
//
//------------------------------------------------------------------------------
//
// Bluetooth RFCOMM Layer
//
//
// Module Name:
//
// rfcomm.cxx
//
// Abstract:
//
// This file implements Bluetooth RFCOMM Layer
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <svsutil.hxx>
#if ! defined (UNDER_CE)
#include <stddef.h>
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_hcip.h>
#include <bt_ddi.h>
#define RFCOMM_T1 60
#define RFCOMM_T2 60
#define RFCOMM_T3 5
#define RFCOMM_N1 127
#define RFCOMM_MAX_CH 31
#define RFCOMM_SCALE 10
// link stages (phys & log)
#define DORMANT 0x00
#define CONNECTING 0x01
#define CONNECTED 0x02
#define CONFIG_REQ_DONE 0x04 // L2CAP Only
#define CONFIG_IND_DONE 0x08 // L2CAP Only
#define L2CAPUP 0x0e // L2CAP Only
#define SABM0UA 0x10 // L2CAP Only
#define UP 0x1e
#define CALL_L2CAP_LINK_SETUP 0x01
#define CALL_L2CAP_LINK_CONFIG 0x02
#define CALL_RFCOMM_SABM0 0x03
#define CALL_RFCOMM_SABMN 0x04
#define CALL_RFCOMM_DISCN 0x05
#define CALL_RFCOMM_USERDATA 0x06
#define CALL_RFCOMM_SIGNALDATA 0x07
#define RFCOMM_SIGNAL_ASYNC 0x1
#define RFCOMM_SIGNAL_RESPONSE 0x2
#define RFCOMM_SIGNAL_NONE 0x3
//
// Protocol settings are loosely derived from Whistler RFCOMM protocol.h (by stana)
//
struct TS_FRAME_HEADER {
unsigned char ucAddress;
unsigned char ucControl;
unsigned char ucLength;
};
struct TS_FRAME_HEADER_X {
unsigned char ucAddress;
unsigned char ucControl;
unsigned char ucLength;
unsigned char ucExtLength;
unsigned char ucCredits;
};
struct TS_FRAME_FOOTER {
unsigned char ucFcs;
};
struct TS_FRAME {
TS_FRAME_HEADER h;
TS_FRAME_FOOTER f;
};
#define EA_BIT 0x01
#define CR_BIT 0x02
#define DLCI_DIRECTION_BIT 0x04
#define CHANNEL_MASK 0x1f
#define DLCI_MASK 0x2f
#define DLCI_FROM_CHANNEL(c, i) ((((c)&CHANNEL_MASK)<<1) + ((i) ? 0 : 1))
#define DLCI_FROM_ADDRESS(a) (((a)>>2)&DLCI_MASK)
#define CHANNEL_FROM_ADDRESS(a) (((a)>>3)&CHANNEL_MASK)
#define CTL_SABM 0x2f
#define CTL_UA 0x63
#define CTL_DM 0x0f
#define CTL_DISC 0x43
#define CTL_UIH 0xef
#define CTL_PF 0x10
inline int TS_LENGTH(unsigned char *p) {
return (p[0] & EA_BIT ? p[0] : p[0] | (p[1] << 8)) >> 1;
}
#define TS_SIZEOFLENGTH(p) (((*(unsigned char *)(p))&EA_BIT) ? 1 : 2)
#define TS_SIZEOFHEADER(h) (sizeof(TS_FRAME_HEADER)+TS_SIZEOFLENGTH(&(h)->Length))
// TEST is an RFCOMM ping. N bytes of data are sent, and must be echoed back
// exactly to complete the test.
#pragma warning (push)
#pragma warning (disable : 4200)
struct MUX_MSG_TEST {
unsigned char Command;
unsigned char Length;
unsigned char Data[0];
};
#pragma warning (pop)
#define MSG_TEST 0x08
// Turn on aggregate flow control
struct MUX_MSG_FCON {
unsigned char Command;
unsigned char Length; // always 0
};
#define MSG_FCON 0x28
// Turn off aggregate flow control
struct MUX_MSG_FCOFF {
unsigned char Command;
unsigned char Length; // always 0
};
#define MSG_FCOFF 0x18
// Modem status command
struct MUX_MSG_MSC {
unsigned char Command;
unsigned char Length; // 2 or 3
unsigned char Address;
unsigned char Signals;
unsigned char Break;
};
#define MSG_MSC 0x38
#define MSC_EA_BIT EA_BIT
#define MSC_FC_BIT BIT(1) // Flow control, clear if we can receive
#define MSC_RTC_BIT BIT(2) // Ready to communicate, set when ready
#define MSC_RTR_BIT BIT(3) // Ready to receive, set when ready
#define MSC_IC_BIT BIT(6) // Incoming call
#define MSC_DV_BIT BIT(7) // Data valid
#define MSC_BREAK_BIT BIT(1) // Set if sending break
#define MSC_SET_BREAK_LENGTH(b, l) ((b) = ((b)&0x3) | (((l)&0xf) << 4))
/* Alignment & packing
struct MUX_MSG_RPN {
unsigned char Command;
unsigned char Length; // 1 or 8
unsigned char Address;
unsigned Baud : 8;
unsigned DataBits : 2;
unsigned StopBits : 1;
unsigned ParityEnabled : 1;
unsigned ParityType : 2;
unsigned Reserved0 : 2;
unsigned XonXoffInput : 1;
unsigned XonXoffOutput : 1;
unsigned RTRInput : 1;
unsigned RTROutput : 1;
unsigned RTCInput : 1;
unsigned RTCOutput : 1;
unsigned Reserved1 : 2;
unsigned XonChar : 8;
unsigned XoffChar : 8;
union {
struct {
unsigned Baud : 1;
unsigned Data : 1;
unsigned Stop : 1;
unsigned Parity : 1;
unsigned ParityType : 1;
unsigned XonChar : 1;
unsigned XofChar : 1;
unsigned Reserved : 1;
unsigned XonXoffInput : 1;
unsigned XonXoffOutput : 1;
unsigned RTRInput : 1;
unsigned RTROutput : 1;
unsigned RTCInput : 1;
unsigned RTCOutput : 1;
unsigned Reserved1 : 2;
};
USHORT Mask;
} Change;
}; */
#define MSG_RPN 0x24
#define RPN_BAUD_2400 0
#define RPN_BAUD_4800 1
#define RPN_BAUD_7200 2
#define RPN_BAUD_9600 3
#define RPN_BAUD_19200 4
#define RPN_BAUD_38400 5
#define RPN_BAUD_57600 6
#define RPN_BAUD_115200 7
#define RPN_BAUD_230400 8
#define RPN_DATA_5 0
#define RPN_DATA_6 1
#define RPN_DATA_7 2
#define RPN_DATA_8 3
#define RPN_PARITY_ODD 0
#define RPN_PARITY_EVEN 1
#define RPN_PARITY_MARK 2
#define RPN_PARITY_SPACE 3
// Remote line status
/* Alignment & packing
struct MUX_MSG_RLS {
unsigned char Command;
unsigned char Length; // Always 2
unsigned char Address;
struct {
unsigned Error : 1; // An error has occurred
unsigned OverrunError : 1; //
unsigned ParityError : 1; // Type of error
unsigned FramingError : 1; //
} LineStatus;
}; */
#define MSG_RLS 0x14
// Parameter negotiation
/* Alignment & packing
struct MUX_MSG_PN {
unsigned char Command;
unsigned char Length;
unsigned IType : 4; // Always 0, (UIH frames)
unsigned ConvergenceLayer : 4;
unsigned Priority : 6;
unsigned Fill0 : 2;
unsigned AckTimer : 8; // Hundredths of a second
unsigned MaxFrameSize : 16;
unsigned MaxRetransmissions : 8;
unsigned WindowSize : 3;
unsigned Fill1 : 5;
}; */
#define MSG_PN 0x20
struct MUX_MSG_NSC {
unsigned char Command;
unsigned char Length; // Always 1
unsigned char CommandNotSupported;
};
#define MSG_NSC 0x04
#define MSG_PSC 0x10
#define MSG_CLD 0x30
#define MSG_SNC 0x34
struct DLCI;
struct Task;
struct Session;
struct RFCOMM_CONTEXT;
struct DLCI {
DLCI *pNext; // Next channel
Session *pSess; // Physical session
RFCOMM_CONTEXT *pOwner; // Owner context
unsigned int channel : 5; // server channel id
unsigned int fLocal : 1; // Channel is local?
unsigned int fStage : 8; // Lifestage of a channel
unsigned int fFCA : 1; // 1 = sent FC signal already
DLCI (Session *a_pSess, unsigned char a_ch, int a_fLocal, RFCOMM_CONTEXT *a_pOwner) {
memset (this, 0, sizeof(*this));
pSess = a_pSess;
pOwner = a_pOwner;
channel= a_ch;
fLocal = a_fLocal ? TRUE : FALSE;
}
void *operator new (size_t iSize);
void operator delete (void *ptr);
};
struct Task {
Task *pNext; // Next task
RFCOMM_CONTEXT *pOwner; // Owner context
void *pContext; // Call context
unsigned int fWhat : 8; // Call type
unsigned int channel : 5; // Channel server id
unsigned int fLocal : 1; // Channel is local
unsigned int fPF : 1; // Does this block the line?
unsigned int fData : 1; // Is this data or signal
unsigned int fUnused : 2; // pad
unsigned int eType : 6; // Signal type
unsigned char signal_length : 4; // Signal packet waiting for session to open
unsigned char signal_dlci_offset : 4; // offset to be filled with DLCI
unsigned char signal_body[10];
Session *pPhysLink;
Task (int a_fWhat, RFCOMM_CONTEXT *a_pOwner, Session *a_pSess) {
memset (this, 0, sizeof(*this));
pOwner = a_pOwner;
fWhat = a_fWhat;
pPhysLink = a_pSess;
if ((fWhat == CALL_RFCOMM_USERDATA) || (fWhat == CALL_RFCOMM_SIGNALDATA))
fData = TRUE;
}
Task (RFCOMM_CONTEXT *a_pOwner, Session *a_pSess, void *a_pContext, unsigned char a_cType) {
memset (this, 0, sizeof(*this));
pOwner = a_pOwner;
pContext = a_pContext;
fWhat = CALL_RFCOMM_SIGNALDATA;
fData = TRUE;
eType = a_cType;
pPhysLink = a_pSess;
}
void *operator new (size_t iSize);
void operator delete (void *ptr);
};
struct Session {
Session *pNext; // Next session
DLCI *pLogLinks; // List of logical channels
BD_ADDR b; // Bluetooth address
unsigned short cid; // L2CAP cid
unsigned int fStage : 8; // Lifestage
unsigned int fIncoming : 1; // DLCI DIRECTION BIT = ! fIncoming
unsigned int fBusy : 1; // Has PF command outstanding
unsigned int fWaitAck : 1; // PF command was removed, but UA/DM is needed
unsigned short inMTU; // L2CAP MTU in
unsigned short outMTU; // L2CAP MTU out
SVSCookie kTimeoutCookie; // Timer handle
int iErr; // Number of physical errors
Session (BD_ADDR *pba) {
memset (this, 0, sizeof(*this));
b = *pba;
fStage = DORMANT;
}
void *operator new (size_t iSize);
void operator delete (void *ptr);
#if defined (DEBUG) || defined (_DEBUG)
unsigned char ucDbgBusyChannel;
#endif
};
struct ServerChannel {
ServerChannel *pNext;
unsigned int channel : 5;
void *operator new (size_t iSize);
void operator delete (void *ptr);
};
struct RFCOMM_CONTEXT : public SVSAllocClass, public SVSRefObj {
RFCOMM_CONTEXT *pNext; // Next context
RFCOMM_EVENT_INDICATION ei; // Event indicators vtable
RFCOMM_CALLBACKS c; // Callbacks vtable
void *pUserContext; // User context
ServerChannel *pReservedChannels;
unsigned int fDefaultServer; // Channel to restrict incoming connections to.
RFCOMM_CONTEXT (void) {
pNext = NULL;
memset (&ei, 0, sizeof(ei));
memset (&c, 0, sizeof(c));
pUserContext = NULL;
pReservedChannels = NULL;
fDefaultServer = FALSE;
}
};
class RFCOMM : public SVSSynch, public SVSRefObj, public SVSAllocClass {
public:
RFCOMM_CONTEXT *pContexts; // List of contexts
Session *pPhysLinks; // List of sessions
Task *pCalls; // List of calls
FixedMemDescr *pfmdSessions; // FMD for sessions
FixedMemDescr *pfmdChannels; // FMD for channels
FixedMemDescr *pfmdCalls; // FMD for calls
FixedMemDescr *pfmdSC; // FMD for server channels
HANDLE hL2CAP; // L2CAP handle
L2CAP_INTERFACE l2cap_if; // L2CAP interface table
int cDataHeaders; // Size of headers at the lower layer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -