|
1 // btincoming.cpp |
|
2 // |
|
3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <e32base.h> |
|
14 #include "btincomingserial.h" |
|
15 #include "btservice.h" |
|
16 #include "btdebug.h" |
|
17 |
|
18 _LIT(KBtSerialPanic, "BTSerial"); |
|
19 void Panic(TBtSerialPanic aReason) |
|
20 { |
|
21 TRACE2("BtIncoming panic %d", aReason); |
|
22 User::Panic(KBtSerialPanic, aReason); |
|
23 }; |
|
24 |
|
25 |
|
26 NONSHARABLE_CLASS(CBtRegQuery) : public CActive |
|
27 { |
|
28 public: |
|
29 CBtRegQuery(CBluetoothIncomingSerialConnection& aOwner); |
|
30 void Start(CBTRegistryResponse& aResponse); |
|
31 private: |
|
32 virtual void RunL(); |
|
33 virtual void DoCancel(); |
|
34 private: |
|
35 CBluetoothIncomingSerialConnection& iOwner; |
|
36 CBTRegistryResponse* iResponse; |
|
37 }; |
|
38 |
|
39 |
|
40 EXPORT_C CBluetoothIncomingSerialConnection* CBluetoothIncomingSerialConnection::NewL(MBtIncomingConnectionObserver& aObserver) |
|
41 { |
|
42 TRACE1("CBluetoothIncomingSerialConnection::NewL"); |
|
43 CBluetoothIncomingSerialConnection* self = new(ELeave)CBluetoothIncomingSerialConnection(aObserver); |
|
44 CleanupStack::PushL(self); |
|
45 self->ConstructL(); |
|
46 CleanupStack::Pop(self); |
|
47 return self; |
|
48 } |
|
49 |
|
50 EXPORT_C CBluetoothIncomingSerialConnection::~CBluetoothIncomingSerialConnection() |
|
51 { |
|
52 TRACE1("CBluetoothIncomingSerialConnection::~CBluetoothIncomingSerialConnection"); |
|
53 delete iService; |
|
54 delete iSocket; |
|
55 iSockServ.Close(); |
|
56 iSdpSession.Close(); |
|
57 } |
|
58 |
|
59 CBluetoothIncomingSerialConnection::CBluetoothIncomingSerialConnection(MBtIncomingConnectionObserver& aObserver) |
|
60 : iObserver(aObserver) |
|
61 { |
|
62 } |
|
63 |
|
64 void CBluetoothIncomingSerialConnection::ConstructL() |
|
65 { |
|
66 TRACE1("+CBluetoothIncomingSerialConnection::ConstructL"); |
|
67 User::LeaveIfError(iSdpSession.Connect()); |
|
68 User::LeaveIfError(iSockServ.Connect()); |
|
69 TUUID serialPortUUID = TUUID(0x1101); |
|
70 iService = CBtService::NewL(serialPortUUID, iSdpSession, iSockServ, *this, KRFCOMM); |
|
71 |
|
72 // create a blank socket for the incoming connection |
|
73 iSocket = CBluetoothSocket::NewL(*this, iSockServ); |
|
74 TRACE1("-CBluetoothIncomingSerialConnection::ConstructL"); |
|
75 } |
|
76 |
|
77 |
|
78 EXPORT_C void CBluetoothIncomingSerialConnection::WaitForConnection() |
|
79 { |
|
80 TRACE1("CBluetoothIncomingSerialConnection::WaitForConnection"); |
|
81 iService->AcceptConnection(*iSocket); |
|
82 } |
|
83 |
|
84 EXPORT_C TBool CBluetoothIncomingSerialConnection::Connected() |
|
85 { |
|
86 TRACE2("CBluetoothIncomingSerialConnection::Connected %d", iSocketReady); |
|
87 return iSocketReady; |
|
88 } |
|
89 |
|
90 EXPORT_C TBTDevAddr CBluetoothIncomingSerialConnection::ConnectedDeviceAddrL() |
|
91 { |
|
92 if (!iSocketReady) User::Leave(KErrNotReady); |
|
93 TBTSockAddr remote; |
|
94 iSocket->RemoteName(remote); |
|
95 return remote.BTAddr(); |
|
96 } |
|
97 |
|
98 EXPORT_C void CBluetoothIncomingSerialConnection::GetConnectedDeviceNameL() |
|
99 { |
|
100 if (iConnectedDevice) return; |
|
101 if (!iSocketReady) User::Leave(KErrNotReady); |
|
102 // lazy construction.... |
|
103 if (!iRegQuery) iRegQuery = new(ELeave)CBtRegQuery(*this); |
|
104 if (iRegQuery->IsActive()) |
|
105 { |
|
106 return; |
|
107 } |
|
108 if (reinterpret_cast<RHandleBase&>(iBtRegServ).Handle() == KNullHandle) |
|
109 { |
|
110 User::LeaveIfError(iBtRegServ.Connect()); |
|
111 } |
|
112 if (iBtReg.SubSessionHandle() == KNullHandle) |
|
113 { |
|
114 User::LeaveIfError(iBtReg.Open(iBtRegServ)); |
|
115 } |
|
116 if (!iRegReponse) iRegReponse = CBTRegistryResponse::NewL(iBtReg); |
|
117 |
|
118 |
|
119 TBTSockAddr remote; |
|
120 iSocket->RemoteName(remote); |
|
121 |
|
122 TBTRegistrySearch findConnected; |
|
123 findConnected.FindAddress(remote.BTAddr()); |
|
124 TRequestStatus stat; |
|
125 iBtReg.CreateView(findConnected, stat); |
|
126 User::WaitForRequest(stat); |
|
127 User::LeaveIfError(stat.Int()); |
|
128 |
|
129 iRegQuery->Start(*iRegReponse); |
|
130 } |
|
131 |
|
132 void CBluetoothIncomingSerialConnection::QueryComplete(TInt aError) |
|
133 { |
|
134 iBtReg.CloseView(); |
|
135 if (aError == KErrNone) |
|
136 { |
|
137 RBTDeviceArray& results = iRegReponse->Results(); |
|
138 if (results.Count() != 1) |
|
139 // we queried by BD address, so should get 1 (or 0) results |
|
140 { |
|
141 aError = KErrNotFound; |
|
142 } |
|
143 if (aError == KErrNone) |
|
144 { |
|
145 TRAP(aError, iConnectedDevice = results[0]->CopyL()); |
|
146 } |
|
147 if (aError == KErrNone) |
|
148 { |
|
149 if (iConnectedDevice->IsValidFriendlyName()) |
|
150 { |
|
151 aError = iDeviceName.Create(iConnectedDevice->FriendlyName()); |
|
152 } |
|
153 else |
|
154 { |
|
155 aError = iDeviceName.Create(iConnectedDevice->DeviceName().Length()); |
|
156 if (aError == KErrNone) |
|
157 { |
|
158 iDeviceName.Copy(iConnectedDevice->DeviceName()); |
|
159 } |
|
160 } |
|
161 if (aError!=KErrNone) |
|
162 { |
|
163 delete iConnectedDevice; |
|
164 iConnectedDevice = NULL; |
|
165 } |
|
166 |
|
167 } |
|
168 } |
|
169 iObserver.BtNameReceived(aError, iDeviceName); |
|
170 } |
|
171 |
|
172 EXPORT_C void CBluetoothIncomingSerialConnection::Write(const TDesC8& aData) |
|
173 { |
|
174 TRACE1("CBluetoothIncomingSerialConnection::Write"); |
|
175 __ASSERT_ALWAYS(iSocketReady, Panic(EBtSerialNotConnected)); |
|
176 __ASSERT_ALWAYS(!iSending, Panic(EBtSerialWritePending)); |
|
177 TInt err = iSocket->Send(aData, 0); |
|
178 if (err==KErrNone) |
|
179 { |
|
180 iSending = ETrue; |
|
181 } |
|
182 else |
|
183 { |
|
184 iObserver.BtWriteComplete(err); |
|
185 } |
|
186 } |
|
187 |
|
188 EXPORT_C void CBluetoothIncomingSerialConnection::CancelWrite() |
|
189 { |
|
190 TRACE1("CBluetoothIncomingSerialConnection::CancelWrite"); |
|
191 iSocket->CancelSend(); |
|
192 iSending = EFalse; |
|
193 } |
|
194 |
|
195 EXPORT_C void CBluetoothIncomingSerialConnection::Read(TDes8& aData) |
|
196 { |
|
197 TRACE1("CBluetoothIncomingSerialConnection::Read"); |
|
198 __ASSERT_ALWAYS(iSocketReady, Panic(EBtSerialNotConnected)); |
|
199 __ASSERT_ALWAYS(!iReceiving, Panic(EBtSerialReadPending)); |
|
200 aData.Zero(); |
|
201 TInt err = iSocket->RecvOneOrMore(aData, 0, iXferLen); |
|
202 if (err==KErrNone) |
|
203 { |
|
204 iReceiving = ETrue; |
|
205 } |
|
206 else |
|
207 { |
|
208 iObserver.BtReadComplete(err); |
|
209 } |
|
210 } |
|
211 |
|
212 EXPORT_C void CBluetoothIncomingSerialConnection::CancelRead() |
|
213 { |
|
214 TRACE1("CBluetoothIncomingSerialConnection::CancelRead"); |
|
215 iSocket->CancelRead(); |
|
216 iReceiving = EFalse; |
|
217 } |
|
218 |
|
219 EXPORT_C void CBluetoothIncomingSerialConnection::ShutDown() |
|
220 { |
|
221 iSocket->Shutdown(RSocket::EImmediate); |
|
222 } |
|
223 |
|
224 void CBluetoothIncomingSerialConnection::HandleConnectCompleteL(TInt _BTDEB(aErr)) |
|
225 { |
|
226 TRACE2("CBluetoothIncomingSerialConnection::HandleConnectCompleteL(%d)", aErr); |
|
227 } |
|
228 |
|
229 void CBluetoothIncomingSerialConnection::HandleAcceptCompleteL(TInt _BTDEB(aErr)) |
|
230 { |
|
231 TRACE2("CBluetoothIncomingSerialConnection::HandleAcceptCompleteL(%d)", aErr); |
|
232 } |
|
233 |
|
234 void CBluetoothIncomingSerialConnection::HandleShutdownCompleteL(TInt aErr) |
|
235 { |
|
236 TRACE2("CBluetoothIncomingSerialConnection::HandleShutdownCompleteL(%d)", aErr); |
|
237 iObserver.BtShutdownComplete(aErr); |
|
238 } |
|
239 |
|
240 void CBluetoothIncomingSerialConnection::HandleSendCompleteL(TInt aErr) |
|
241 { |
|
242 TRACE1("CBluetoothIncomingSerialConnection::HandleSendCompleteL"); |
|
243 __ASSERT_ALWAYS(iSending, PANIC()); |
|
244 iSending = EFalse; |
|
245 iObserver.BtWriteComplete(aErr); |
|
246 } |
|
247 |
|
248 void CBluetoothIncomingSerialConnection::HandleReceiveCompleteL(TInt aErr) |
|
249 { |
|
250 TRACE1("CBluetoothIncomingSerialConnection::HandleReceiveCompleteL"); |
|
251 __ASSERT_ALWAYS(iReceiving, PANIC()); |
|
252 iReceiving = EFalse; |
|
253 iObserver.BtReadComplete(aErr); |
|
254 } |
|
255 |
|
256 void CBluetoothIncomingSerialConnection::HandleIoctlCompleteL(TInt _BTDEB(aErr)) |
|
257 { |
|
258 TRACE2("CBluetoothIncomingSerialConnection::HandleIoctlCompleteL(%d)", aErr); |
|
259 } |
|
260 |
|
261 void CBluetoothIncomingSerialConnection::HandleActivateBasebandEventNotifierCompleteL(TInt _BTDEB(aErr), TBTBasebandEventNotification& /*aEventNotification*/) |
|
262 { |
|
263 TRACE2("CBluetoothIncomingSerialConnection::HandleActivateBasebandEventNotifierCompleteL(%d)", aErr); |
|
264 } |
|
265 |
|
266 void CBluetoothIncomingSerialConnection::HandleNewConnection(CBluetoothSocket* aConnectedSocket) |
|
267 { |
|
268 TRACE1("CBluetoothIncomingSerialConnection::HandleNewConnection"); |
|
269 __ASSERT_ALWAYS(iSocket == aConnectedSocket, PANIC()); |
|
270 iSocketReady = ETrue; |
|
271 iObserver.BtSerialConnected(); |
|
272 } |
|
273 |
|
274 void CBluetoothIncomingSerialConnection::HandleConnectFailed(TInt aError) |
|
275 { |
|
276 TRACE2("CBluetoothIncomingSerialConnection::HandleConnectFailed", aError); |
|
277 iSocketReady = EFalse; |
|
278 iObserver.BtSerialError(aError); |
|
279 } |
|
280 |
|
281 CBtRegQuery::CBtRegQuery(CBluetoothIncomingSerialConnection& aOwner) |
|
282 : CActive(CActive::EPriorityStandard), iOwner(aOwner) |
|
283 { |
|
284 CActiveScheduler::Add(this); |
|
285 } |
|
286 |
|
287 void CBtRegQuery::Start(CBTRegistryResponse& aBtResponse) |
|
288 { |
|
289 iResponse = &aBtResponse; |
|
290 iResponse->Start(iStatus); |
|
291 SetActive(); |
|
292 } |
|
293 |
|
294 void CBtRegQuery::RunL() |
|
295 { |
|
296 iOwner.QueryComplete(iStatus.Int()); |
|
297 } |
|
298 |
|
299 void CBtRegQuery::DoCancel() |
|
300 { |
|
301 iResponse->Cancel(); |
|
302 // nasty race condition inside CBTRegistryResponse which means the cancal call may not |
|
303 // request out TRequestStatus (if DoCancel doesn't need to be called) |
|
304 if (iStatus == KRequestPending) |
|
305 { |
|
306 TRequestStatus* stat = &iStatus; |
|
307 User::RequestComplete(stat, KErrCancel); |
|
308 } |
|
309 } |
|
310 |