|
1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #ifndef RFCOMMMUXER_H |
|
17 #define RFCOMMMUXER_H |
|
18 |
|
19 #include <es_prot.h> |
|
20 #include <bttypes.h> |
|
21 #include "rfcommsap.h" |
|
22 #include "rfcommframe.h" |
|
23 #include "rfcommflow.h" |
|
24 |
|
25 class CRfcommSignalFrame; |
|
26 class CRfcommMuxChannel; |
|
27 class CRfcommFlowStrategyFactory; |
|
28 class CMuxChannelStateFactory; |
|
29 class TRfcommFlowStrategy; |
|
30 /** |
|
31 Acts as the TS7.10 multiplexer. |
|
32 |
|
33 There is one of these per remote device, as only one RFCOMM |
|
34 multiplexer session can be run between two devices. This class |
|
35 acts as an internal socket binding to a lower level SAP. Thus we |
|
36 derive from MSocketNotify so that the SAP can directly notify us of events. |
|
37 |
|
38 **/ |
|
39 NONSHARABLE_CLASS(CRfcommMuxer) : public CBase, public MSocketNotify |
|
40 { |
|
41 friend class CRfcommProtocol; |
|
42 friend class CRfcommMuxChannel; |
|
43 |
|
44 public: |
|
45 // Create/destroy |
|
46 |
|
47 // Two flavours of factory - one takes an L2CAP connection which should |
|
48 // be used by the Mux channel associated with this muxer. The other |
|
49 // takes a CProtocolBase which it can use to create its own connection |
|
50 static CRfcommMuxer* NewL(CRfcommProtocol& aProt, CProtocolBase& aL2CAP, |
|
51 CMuxChannelStateFactory& aFactory); |
|
52 |
|
53 static CRfcommMuxer* NewL(CRfcommProtocol& aProt, CServProviderBase* aSAP, |
|
54 CMuxChannelStateFactory& aFactory); |
|
55 |
|
56 ~CRfcommMuxer(); |
|
57 // Interface for the Protocol to request services |
|
58 void Bind(TBTDevAddr& aAddr); |
|
59 void AddSAP(CRfcommSAP& aSAP); |
|
60 void DetachSAP(CRfcommSAP& aSAP); |
|
61 |
|
62 void GetInboundServerChannelsInUse(TFixedArray<TBool, KMaxRfcommServerChannel>& aChannelInUse); |
|
63 |
|
64 // Interface for the SAPs to request actions |
|
65 TUint8 MakeOutboundDLCI(TUint8 aServerChannel); |
|
66 TUint8 MakeInboundDLCI(TUint8 aServerChannel); |
|
67 TUint8 MakeServerChannel(TUint8 aDLCI); |
|
68 |
|
69 TInt SendSABM(CRfcommSAP& aSAP); |
|
70 TInt SendMSC(CRfcommSAP& aSAP, TUint8 aFlags); |
|
71 TInt SendMSCRsp(CRfcommSAP& aSAP, TUint8 aFlags); |
|
72 TInt SendRLS(CRfcommSAP& aSAP, TUint8 aStatus); |
|
73 TInt SendRLSRsp(CRfcommSAP& aSAP, TUint8 aStatus); |
|
74 TInt SendRPN(CRfcommSAP& aSAP, TBool aCommand, TUint8 aLength, |
|
75 const TRfcommRPNTransaction& aRPNTransaction); |
|
76 TInt SendUA(CRfcommSAP& aSAP); |
|
77 TInt SendUA(TUint8 aDLCI); |
|
78 TInt SendPN(CRfcommSAP& aSAP, const TRfcommPortParams& params); |
|
79 TInt SendPNResponse(CRfcommSAP& aSAP, const TRfcommPortParams& params); |
|
80 void SendDISC(CRfcommSAP& aSAP); |
|
81 void SendDISC(TUint8 aDLCI); |
|
82 void SendDM(TUint8 aDLCI); |
|
83 TInt SendFCon(); |
|
84 TInt SendFCoff(); |
|
85 void Donate(CRfcommSAP& aSAP, TUint8 aCredit); //TRY_CBFC |
|
86 TInt Write(CRfcommSAP& aSAP, TUint8 aCredit, const TDesC8& aData); |
|
87 void SetCanHandleData(CRfcommSAP& aSAP, TBool aCanReceive); |
|
88 TInt GetMaxDataSize() const; |
|
89 TInt Ioctl(TUint aLevel, TUint aName, TDes8* aOption); |
|
90 void CancelIoctl(TUint aLevel, TUint aName); |
|
91 TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption); |
|
92 TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption); |
|
93 |
|
94 // From MSocketNotify |
|
95 void NewData(TUint aCount); |
|
96 void CanSend(); |
|
97 void ConnectComplete(); |
|
98 void ConnectComplete(const TDesC8& aConnectData); |
|
99 void ConnectComplete(CServProviderBase& aSSP); |
|
100 void ConnectComplete(CServProviderBase& aSSP,const TDesC8& aConnectData); |
|
101 void CanClose(TDelete aDelete=EDelete); |
|
102 void CanClose(const TDesC8& aDisconnectData,TDelete aDelete=EDelete); |
|
103 void Error(TInt anError,TUint anOperationMask=EErrorAllOperations); |
|
104 void Disconnect(void); |
|
105 void Disconnect(TDesC8& aDisconnectData); |
|
106 void IoctlComplete(TDesC8 *aBuf); |
|
107 |
|
108 void NoBearer(const TDesC8& /*aConnectionInf*/) {}; |
|
109 void Bearer(const TDesC8& /*aConnectionInf*/) {}; |
|
110 |
|
111 // Other functions |
|
112 void PropagateIoctlCompletion(TInt aError, TUint aIoctlLevel, TUint aIoctlName, TDesC8* aBuf); |
|
113 void FrameResponseTimeout(CRfcommFrame* aFrame); |
|
114 |
|
115 void ClearResponseQueue(CRfcommSAP& aSAP); |
|
116 void ClearOutboundQueue(CRfcommSAP& aSAP); |
|
117 |
|
118 void MuxChannelUp(); |
|
119 void MuxChannelDown(); // the MuxChannel has gone down - so notify SAPs |
|
120 void MuxChannelError(TBool aFatal, TInt anError); |
|
121 void MuxChannelClosed(); // the MuxChannel has gone down - no need for the muxer |
|
122 void CloseSAPs(); |
|
123 const TBTDevAddr& RemoteBTAddr() const; |
|
124 CRfcommSAP* FindSAP(const TUint8 aDLCI); |
|
125 //TRY_CBFC |
|
126 void DisallowCBFC(); |
|
127 void AllowCBFC(); |
|
128 TRfcommFlowStrategy* FlowStrategy(); |
|
129 CRfcommFlowStrategyFactory::TFlowStrategies FlowType(); |
|
130 TBool SetFlowType(CRfcommFlowStrategyFactory::TFlowStrategies aFlowType); |
|
131 |
|
132 |
|
133 |
|
134 private: |
|
135 |
|
136 enum TInitiationDirection |
|
137 { |
|
138 KInitiationDirectionIncoming, // 0 |
|
139 KInitiationDirectionOutgoing // 1 |
|
140 }; |
|
141 |
|
142 CRfcommMuxer(CRfcommProtocol& aProtocol, TInitiationDirection); |
|
143 void ConstructL(CMuxChannelStateFactory& aFactory, CProtocolBase& aL2CAP); |
|
144 void ConstructL(CMuxChannelStateFactory& aFactory, CServProviderBase* aSAP); |
|
145 void CommonConstructL(); |
|
146 |
|
147 // Processing incoming frames |
|
148 void ProcessFrame(); |
|
149 void ParseCtrlMessageL(); |
|
150 void ParsePNL(TInt aOffset, TInt aLen, TUint8& aDLCI, TRfcommPortParams& aParams); |
|
151 void ParseRPN(TInt aOffset, TInt aLen, TUint8& aDLCI, |
|
152 TRfcommRPNTransaction* aRPNTransactionPtr=NULL); |
|
153 void ProcessDataFrame(TUint8 aDLCI, TBool aPoll); |
|
154 TInt GetTypeFieldL(TInt& aType, TInt aPos); |
|
155 TInt GetLengthFieldL(TInt& aLen, TInt aPos); |
|
156 void HandleDISC(TUint8 aDLCI); |
|
157 void HandleSABM(TUint8 aDLCI); |
|
158 void HandleUA(TUint8 aDLCI); |
|
159 void HandleDM(TUint8 aDLCI); |
|
160 void HandlePN(TBool aCommand, TUint8 aDLCI, TRfcommPortParams& aParams); |
|
161 void HandleRPN(const TBool& aCommand, const TUint8& aDLCI, |
|
162 const TRfcommRPNTransaction* aRPNTransactionPtr=NULL); |
|
163 void HandleTest(TBool aCommand, TInt aOffset, TInt aLen); |
|
164 void HandleFCon(TBool aCommand); |
|
165 void HandleFCoff(TBool aCommand); |
|
166 void HandleMSC(TBool aCommand, TUint8 aDLCI, TUint8 aSignals); |
|
167 void HandleRLS(TBool aCommand, TUint8 aDLCI, TUint8 aStatus); |
|
168 |
|
169 // Packet utility functions |
|
170 TBool CheckFCS(TUint8 aFCS, TUint8 aCtrl); |
|
171 TUint8 DecodeDLCI(TUint8 aAddr); |
|
172 void DecodeLengthAndCredit(TBool aCBFC); |
|
173 TUint8 BuildAddr(TUint8 aDLCI, TBool aCommand); |
|
174 void EnqueFrame(CRfcommFrame* aFrm); |
|
175 void TryToSend(); |
|
176 TInt CtrlFrameResponse(TUint8 aDLCI); |
|
177 void MuxCtrlResponse(TUint8 aType); |
|
178 void MuxCtrlResponseDM(TUint8 aDLCI); |
|
179 |
|
180 // Flow control |
|
181 void SetSendBlocked(CRfcommSAP& aSAP, TBool aState); |
|
182 void SignalSAPsCanSend(); |
|
183 TBool ClearToSend() const |
|
184 {return iCanSend;} |
|
185 void SetCanSend(TBool aState) //< True if OK to send |
|
186 {iCanSend=aState;} |
|
187 TBool L2CAPBlocked() const |
|
188 {return iL2CAPSendBlocked;} |
|
189 void L2CAPBlocked(TBool aState) |
|
190 {iL2CAPSendBlocked=aState;} |
|
191 |
|
192 // Constructing packets |
|
193 CRfcommMuxCtrlFrame* NewSignalFrame(TInt aCommandLength, TBool aCommand, CRfcommSAP* aSAP =NULL); |
|
194 CRfcommCtrlFrame* NewFrame(CRfcommSAP* aSAP =NULL); |
|
195 CRfcommDataFrame* NewDataFrame(TUint8 aDLCI, TInt aLen, TUint8 aCredit, CRfcommSAP* aSAP=NULL); |
|
196 |
|
197 // Sending packets |
|
198 TInt TransmitSABM(TUint8 aDLCI, CRfcommSAP* aSAP =NULL); |
|
199 TInt TransmitUA(TUint8 aDLCI, CRfcommSAP* aSAP =NULL); |
|
200 TInt TransmitDISC(TUint8 aDLCI, CRfcommSAP* aSAP =NULL); |
|
201 TInt TransmitDM(TUint8 aDLCI, TBool aPFBit, CRfcommSAP* aSAP =NULL); |
|
202 TInt TransmitPN(TUint8 aDLCI, TBool aCommand, const TRfcommPortParams& aParams, |
|
203 CRfcommSAP* aSAP =NULL); |
|
204 TInt TransmitRPN(TUint8 aDLCI, TBool aCommand, TUint8 aLen, |
|
205 const TRfcommRPNTransaction& aRPNTransaction, CRfcommSAP* aSAP = NULL); |
|
206 TInt TransmitNSC(TBool aCommand, TUint8 aType); |
|
207 TInt TransmitFCon(TBool aCommand, CRfcommSAP* aSAP =NULL); |
|
208 TInt TransmitFCoff(TBool aCommand, CRfcommSAP* aSAP =NULL); |
|
209 TInt TransmitMSC(TUint8 aDLCI, TBool aCommand, TUint8 aSignals, |
|
210 CRfcommSAP* aSAP =NULL); |
|
211 TInt TransmitTest(TBool aCommand, const TDesC8& aData, CRfcommSAP* aSAP =NULL); |
|
212 TInt TransmitRLS(TBool aCommand, TUint8 aDLCI, TUint8 aStatus, |
|
213 CRfcommSAP* aSAP =NULL); |
|
214 |
|
215 |
|
216 // Callbacks & timers |
|
217 static TInt IdleTimerExpired(TAny* aMux); |
|
218 static TInt TryToSendCallbackStatic(TAny* aMux); |
|
219 void TryToSendCallback(); |
|
220 void CheckForIdle(TBool aClosing = EFalse); |
|
221 void QueIdleTimer(); |
|
222 void DequeIdleTimer(); |
|
223 |
|
224 // Utility |
|
225 void DeleteQueuedFrames(); |
|
226 CRfcommSAP* FindConnectedOrListeningSAP(const TUint8 aDLCI); |
|
227 TUint8 MakeDLCI(TUint8 aServerChannel, TUint8 aDirectionBit); |
|
228 |
|
229 // Reception of data from L2CAP |
|
230 TBool CanProcessNewData() const; |
|
231 void SetNoFreeSpace(TInt aDLCI, TBool aNoSpace); |
|
232 |
|
233 // Debug |
|
234 #ifdef __FLOG_ACTIVE |
|
235 void ExplainOutgoingFrame(CRfcommFrame* aFrm, CRfcommMuxer* aMux ); |
|
236 void LogMuxCommand(CRfcommSAP* aSAP, CRfcommMuxer* aMux, TUint8 aCommand); |
|
237 #endif |
|
238 |
|
239 // Data items |
|
240 TDblQue<CRfcommSAP> iSAPs; //< SAPs using this Mux |
|
241 TDblQue<CRfcommFrame> iOutboundQ; //< Frames to send |
|
242 TDblQue<CRfcommFrame> iResponseQ; //< Frames waiting for a response |
|
243 TInt iOutboundQLength; |
|
244 CRfcommProtocol& iProtocol; |
|
245 CServProviderBase* iBoundSAP; |
|
246 TInt iL2CAPMTU; |
|
247 TBTDevAddr iRemoteAddr; |
|
248 const TInt iDirection; //< 1 if we are initiating, else 0 |
|
249 |
|
250 TBool iClosing; //< True if we are closing down our channel |
|
251 TDeltaTimerEntry iIdleTimerEntry; //< Disconnection idle timer |
|
252 TBool iIdleTimerQueued; |
|
253 TInt iMuxIdleTimeout; |
|
254 |
|
255 CAsyncCallBack* iSendCallback; |
|
256 HBufC8* iNextPacket; // Next packet coming up from L2CAP |
|
257 |
|
258 TInt iCurrentHeaderLength; //< Length of the current frame's header |
|
259 TInt iCurrentDataLength; //< Length of the current frame's data |
|
260 |
|
261 // Ioctls |
|
262 TUint iIoctlLevel; |
|
263 TUint iIoctlName; |
|
264 |
|
265 // Flow control |
|
266 TBool iCanSend; //< False if remote has asked us not to send (FCoff) |
|
267 TDblQue<CRfcommSAP> iBlockedSAPs; //< SAPs that are blocked |
|
268 // Control over reading from L2CAP |
|
269 TInt iPacketsWaiting; //< Number of packets L2CAP has for us |
|
270 TUint32 iSAPNoFreeSpaceMask[2]; //< Mask showing which SAP have no space left |
|
271 TInt iDataFramesSent; |
|
272 // Mux channel |
|
273 CRfcommMuxChannel* iMuxChannel; |
|
274 TBool iL2CAPSendBlocked; // Is L2CAP ok to send data? |
|
275 //TRY_CBFC |
|
276 TBool iCBFCDisallowed; // ensure flow strategy set to Mux type when object is instantiated |
|
277 TBool iTriedCBFC; // have we tried to set CBFC ? |
|
278 TInt iCurrentCredit; // a temporary store for the received frame credit |
|
279 TInt iInitialTxCredit; // used as default credit for new SAPs |
|
280 TRfcommFlowStrategy* iFlowStrategy; |
|
281 |
|
282 // Go on a Q |
|
283 TDblQueLink iLink; |
|
284 }; |
|
285 |
|
286 |
|
287 #endif |