|
1 /* |
|
2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: BT RFComm socket |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <badesca.h> |
|
20 #include "btmrfcommsock.h" |
|
21 #include "btmsockobserver.h" |
|
22 #include "debug.h" |
|
23 |
|
24 // Constant for listening queue size |
|
25 const TInt KListenQueSize = 1; |
|
26 |
|
27 // ======== MEMBER FUNCTIONS ======== |
|
28 |
|
29 CBtmRfcommSock* CBtmRfcommSock::NewL(MBtmSockObserver& aObserver, RSocketServ& aServer) |
|
30 { |
|
31 CBtmRfcommSock* self = new (ELeave) CBtmRfcommSock(aObserver, aServer); |
|
32 CleanupStack::PushL(self); |
|
33 self->ConstructL(); |
|
34 CleanupStack::Pop(self); |
|
35 return self; |
|
36 } |
|
37 |
|
38 CBtmRfcommSock::~CBtmRfcommSock() |
|
39 { |
|
40 TRACE_FUNC_ENTRY |
|
41 iAda.Close(); |
|
42 delete iDataSocket; |
|
43 delete iListenSocket; |
|
44 iInData.Close(); |
|
45 iOutData.Close(); |
|
46 delete iOutDataQueue; |
|
47 TRACE_FUNC_EXIT |
|
48 } |
|
49 |
|
50 // --------------------------------------------------------- |
|
51 // CBtmRfcommSock::Connect |
|
52 // --------------------------------------------------------- |
|
53 // |
|
54 void CBtmRfcommSock::ConnectL(TBTSockAddr& aAddr, TUint aService) |
|
55 { |
|
56 TRACE_FUNC_ENTRY |
|
57 TProtocolDesc pInfo; |
|
58 LEAVE_IF_ERROR(iServer.FindProtocol(TProtocolName(KRFCOMMDesC), pInfo)); |
|
59 if (!iDataSocket) |
|
60 { |
|
61 iDataSocket = CBluetoothSocket::NewL(*this, iServer, pInfo.iSockType, pInfo.iProtocol); |
|
62 } |
|
63 LEAVE_IF_ERROR(iDataSocket->Connect(aAddr)); |
|
64 iService = aService; |
|
65 iRemote = TBTDevAddr(); |
|
66 iRemoteHasConnected = EFalse; |
|
67 TRACE_FUNC_EXIT |
|
68 } |
|
69 |
|
70 // --------------------------------------------------------- |
|
71 // CBtmRfcommSock::CancelActiveConnectSocket |
|
72 // --------------------------------------------------------- |
|
73 // |
|
74 void CBtmRfcommSock::CancelConnect() |
|
75 { |
|
76 if (iDataSocket) |
|
77 { |
|
78 TRACE_FUNC_ENTRY |
|
79 iDataSocket->CancelConnect(); |
|
80 TRACE_FUNC_EXIT |
|
81 } |
|
82 } |
|
83 |
|
84 TBool CBtmRfcommSock::AccessoryInitiatedConnection() |
|
85 { |
|
86 return iRemoteHasConnected; |
|
87 } |
|
88 |
|
89 |
|
90 TUint CBtmRfcommSock::ListenL(TUint aService, const TBTServiceSecurity& aSec, TUint aLastUsedPort) |
|
91 { |
|
92 TRACE_FUNC_ENTRY |
|
93 TRACE_ASSERT(!iListenSocket, EBTPanicRfcommAlreadyListen) |
|
94 TRACE_ASSERT(!iDataSocket, EBTPanicRfcommSockInuse) |
|
95 TProtocolDesc pInfo; |
|
96 LEAVE_IF_ERROR(iServer.FindProtocol(TProtocolName(KRFCOMMDesC), pInfo)); |
|
97 iListenSocket = CBluetoothSocket::NewL(*this, iServer, pInfo.iSockType, pInfo.iProtocol); |
|
98 TRfcommSockAddr addr; |
|
99 addr.SetSecurity(aSec); |
|
100 |
|
101 TRACE_INFO((_L("Trying lastused port %d"), aLastUsedPort)) |
|
102 addr.SetPort(aLastUsedPort); |
|
103 TInt error = iListenSocket->Bind(addr); |
|
104 if ( error ) |
|
105 { |
|
106 TRACE_INFO((_L("Trying KRfcommPassiveAutoBind"))) |
|
107 addr.SetPort(KRfcommPassiveAutoBind); |
|
108 LEAVE_IF_ERROR(iListenSocket->Bind(addr)); |
|
109 } |
|
110 LEAVE_IF_ERROR(iListenSocket->Listen(KListenQueSize)); |
|
111 iDataSocket = CBluetoothSocket::NewL(*this, iServer); |
|
112 LEAVE_IF_ERROR(iListenSocket->Accept(*iDataSocket)); |
|
113 iService = aService; |
|
114 TRACE_FUNC_EXIT |
|
115 iRemote = TBTDevAddr(); |
|
116 return iListenSocket->LocalPort(); |
|
117 } |
|
118 |
|
119 void CBtmRfcommSock::CancelListen() |
|
120 { |
|
121 if (iListenSocket) |
|
122 { |
|
123 TRACE_FUNC_ENTRY |
|
124 iListenSocket->CancelAccept(); |
|
125 TRACE_FUNC_EXIT |
|
126 } |
|
127 } |
|
128 |
|
129 void CBtmRfcommSock::Disconnect(RSocket::TShutdown aHow) |
|
130 { |
|
131 TRACE_FUNC_ENTRY |
|
132 if (iDataSocket) |
|
133 { |
|
134 iAda.ActivateActiveRequester(); |
|
135 iDataSocket->CancelWrite(); |
|
136 iDataSocket->CancelRecv(); |
|
137 iDataSocket->CancelIoctl(); |
|
138 iDataSocket->Shutdown(aHow); |
|
139 } |
|
140 iRemote = TBTDevAddr(); |
|
141 TRACE_FUNC_EXIT |
|
142 } |
|
143 |
|
144 void CBtmRfcommSock::WriteL(const TDesC8& aData) |
|
145 { |
|
146 TRACE_FUNC_ENTRY |
|
147 TRACE_ASSERT(iDataSocket != NULL, EBTPanicObjectUninitialized) |
|
148 if (!iOutDataQueue) |
|
149 { |
|
150 iOutDataQueue = new (ELeave) CDesC8ArrayFlat(1); |
|
151 } |
|
152 iOutDataQueue->AppendL(aData); |
|
153 SendPacketL(); |
|
154 TRACE_FUNC_EXIT |
|
155 } |
|
156 |
|
157 void CBtmRfcommSock::CancelWrite() |
|
158 { |
|
159 if (iDataSocket) |
|
160 { |
|
161 TRACE_FUNC_ENTRY |
|
162 iDataSocket->CancelWrite(); |
|
163 iOutDataQueue->Reset(); |
|
164 TRACE_FUNC_EXIT |
|
165 } |
|
166 } |
|
167 |
|
168 const TBTDevAddr& CBtmRfcommSock::Remote() const |
|
169 { |
|
170 return iRemote; |
|
171 } |
|
172 |
|
173 TInt CBtmRfcommSock::RequestMasterRole() |
|
174 { |
|
175 TRACE_FUNC |
|
176 TRACE_ASSERT(iDataSocket, EBTPanicNullPointer) |
|
177 TUint32 basebandState = 0; |
|
178 TInt err = iDataSocket->PhysicalLinkState( basebandState ); |
|
179 if (!err && (basebandState & ENotifySlave)) |
|
180 { |
|
181 err = iDataSocket->RequestMasterRole(); |
|
182 } |
|
183 return err; |
|
184 } |
|
185 |
|
186 TBool CBtmRfcommSock::IsInSniff() const |
|
187 { |
|
188 return iInSniff; |
|
189 } |
|
190 |
|
191 TInt CBtmRfcommSock::ActivateBasebandEventNotification(TInt aNotification) |
|
192 { |
|
193 TRACE_FUNC |
|
194 TRACE_ASSERT(iDataSocket, EBTPanicNullPointer) |
|
195 iBBNotificationMode = aNotification; |
|
196 return iDataSocket->ActivateBasebandEventNotifier(aNotification); |
|
197 } |
|
198 |
|
199 void CBtmRfcommSock::SetObserver(MBtmSockObserver& aObserver) |
|
200 { |
|
201 TRACE_FUNC |
|
202 iObserver = &aObserver; |
|
203 } |
|
204 |
|
205 TUint CBtmRfcommSock::Service() const |
|
206 { |
|
207 return iService; |
|
208 } |
|
209 |
|
210 TInt CBtmRfcommSock::ActivateSniffRequester() |
|
211 { |
|
212 if (iDataSocket) |
|
213 return iAda.ActivateSniffRequester(); |
|
214 else |
|
215 return KErrGeneral; |
|
216 } |
|
217 |
|
218 void CBtmRfcommSock::RequestLinkToActiveMode() |
|
219 { |
|
220 if (iDataSocket) |
|
221 { |
|
222 TInt err = iAda.ActivateActiveRequester(); |
|
223 TRACE_INFO((_L("ada.ActivateActiveRequester err %d"), err)) |
|
224 } |
|
225 TRACE_FUNC |
|
226 } |
|
227 |
|
228 void CBtmRfcommSock::HandleConnectCompleteL(TInt aErr) |
|
229 { |
|
230 TRACE_FUNC_ENTRY |
|
231 TRACE_INFO((_L("err %d"), aErr)) |
|
232 |
|
233 // Process the connect complete before issuing a receive request to ensure that |
|
234 // we are ready to process the data when it is received. |
|
235 iObserver->RfcommConnectCompletedL(aErr); |
|
236 |
|
237 if (!aErr) |
|
238 { |
|
239 TBTSockAddr sockAddr; |
|
240 iDataSocket->RemoteName(sockAddr); |
|
241 iRemote = sockAddr.BTAddr(); |
|
242 iInData.ReAllocL(256); |
|
243 RequestMasterRole(); |
|
244 TInt err = iAda.Open(iServer, iRemote); |
|
245 TRACE_INFO((_L("ada.Open err %d"), err)) |
|
246 iDataSocket->ActivateBasebandEventNotifier(ENotifyAnyPowerMode | ENotifyAnyRole | |
|
247 ENotifySCOLinkUp | ENotifySCOLinkDown | |
|
248 ENotifySCOLinkError | ENotifyPhysicalLinkUp | |
|
249 ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError); |
|
250 ReceiveL(); |
|
251 } |
|
252 TRACE_FUNC_EXIT |
|
253 } |
|
254 |
|
255 void CBtmRfcommSock::HandleAcceptCompleteL(TInt aErr) |
|
256 { |
|
257 TRACE_FUNC_ENTRY |
|
258 |
|
259 iRemoteHasConnected = ETrue; |
|
260 |
|
261 // Process the accept complete before issuing a receive request to ensure that |
|
262 // we are ready to process the data when it is received. |
|
263 iObserver->RfcommAcceptCompletedL(aErr, iService); |
|
264 |
|
265 if (!aErr) |
|
266 { |
|
267 TBTSockAddr sockAddr; |
|
268 iDataSocket->RemoteName(sockAddr); |
|
269 iRemote = sockAddr.BTAddr(); |
|
270 iInData.ReAllocL(256); |
|
271 RequestMasterRole(); |
|
272 TInt err = iAda.Open(iServer, iRemote); |
|
273 TRACE_INFO((_L("ada.Open err %d"), err)) |
|
274 iDataSocket->ActivateBasebandEventNotifier(ENotifyAnyPowerMode | ENotifyAnyRole | |
|
275 ENotifySCOLinkUp | ENotifySCOLinkDown | |
|
276 ENotifySCOLinkError | ENotifyPhysicalLinkUp | |
|
277 ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError); |
|
278 ReceiveL(); |
|
279 } |
|
280 TRACE_FUNC_EXIT |
|
281 } |
|
282 |
|
283 void CBtmRfcommSock::HandleShutdownCompleteL(TInt aErr) |
|
284 { |
|
285 TRACE_FUNC |
|
286 iObserver->RfcommShutdownCompletedL(aErr); |
|
287 } |
|
288 |
|
289 void CBtmRfcommSock::HandleSendCompleteL(TInt aErr) |
|
290 { |
|
291 TRACE_FUNC |
|
292 TRACE_INFO((_L("err %d"), aErr)) |
|
293 iWriting = EFalse; |
|
294 if (!aErr) |
|
295 { |
|
296 SendPacketL(); |
|
297 } |
|
298 else |
|
299 { |
|
300 iObserver->RfcommSendCompletedL(aErr); |
|
301 } |
|
302 } |
|
303 |
|
304 void CBtmRfcommSock::HandleReceiveCompleteL(TInt aErr) |
|
305 { |
|
306 TRACE_FUNC |
|
307 TRACE_INFO((_L("err %d"), aErr)) |
|
308 |
|
309 iObserver->RfcommReceiveCompletedL(aErr, iInData); |
|
310 if (!aErr) |
|
311 { |
|
312 ReceiveL(); |
|
313 } |
|
314 } |
|
315 |
|
316 void CBtmRfcommSock::HandleIoctlCompleteL(TInt aErr) |
|
317 { |
|
318 TRACE_FUNC |
|
319 TRACE_INFO((_L("KL2CAPEchoRequestIoctl callback code: %d"), aErr )) |
|
320 |
|
321 if (aErr) |
|
322 { |
|
323 iObserver->RfcommSendCompletedL(aErr); |
|
324 } |
|
325 } |
|
326 |
|
327 void CBtmRfcommSock::HandleActivateBasebandEventNotifierCompleteL( |
|
328 TInt aErr, TBTBasebandEventNotification& aEventNotification) |
|
329 { |
|
330 TRACE_FUNC_ENTRY |
|
331 if (!aErr) |
|
332 { |
|
333 switch(aEventNotification.EventType()) |
|
334 { |
|
335 case ENotifyActiveMode: |
|
336 { |
|
337 TRACE_INFO(_L( "BB Notif: Active mode" )) |
|
338 iInSniff = EFalse; |
|
339 break; |
|
340 } |
|
341 case ENotifySniffMode: |
|
342 { |
|
343 TRACE_INFO(_L( "BB Notif: Sniff mode" )) |
|
344 break; |
|
345 } |
|
346 case ENotifyMaster: |
|
347 { |
|
348 TRACE_INFO(_L( "BB Notif: Master role")) |
|
349 break; |
|
350 } |
|
351 case ENotifySlave: |
|
352 { |
|
353 TRACE_INFO(_L("BB Notif: Slave role")) |
|
354 break; |
|
355 } |
|
356 case ENotifySCOLinkUp: |
|
357 { |
|
358 TRACE_INFO(_L("BB Notif: SCO up")) |
|
359 break; |
|
360 } |
|
361 case ENotifySCOLinkDown: |
|
362 { |
|
363 TRACE_INFO(_L("BB Notif: SCO down")) |
|
364 |
|
365 TInt err = iDataSocket->Ioctl( KL2CAPEchoRequestIoctl, NULL, KSolBtL2CAP ); |
|
366 |
|
367 TRACE_INFO((_L("KL2CAPEchoRequestIoctl return code: %d"), err )) |
|
368 break; |
|
369 } |
|
370 case ENotifySCOLinkError: |
|
371 { |
|
372 TRACE_INFO(_L("BB Notif: SCO error")) |
|
373 break; |
|
374 } |
|
375 case ENotifyPhysicalLinkUp: |
|
376 { |
|
377 TRACE_INFO(_L("BB Notif: Physical link up")) |
|
378 break; |
|
379 } |
|
380 case ENotifyPhysicalLinkDown: |
|
381 { |
|
382 TRACE_INFO(_L("BB Notif: Physical link down")) |
|
383 break; |
|
384 } |
|
385 case ENotifyPhysicalLinkError: |
|
386 { |
|
387 TRACE_INFO(_L("BB Notif: Physical link error")) |
|
388 break; |
|
389 } |
|
390 default: |
|
391 { |
|
392 TRACE_INFO((_L( "BB Notif: Uninteresting event (0x%08X)"), aEventNotification.EventType())) |
|
393 } |
|
394 }; |
|
395 } |
|
396 TRACE_FUNC_EXIT |
|
397 } |
|
398 |
|
399 void CBtmRfcommSock::ConstructL() |
|
400 { |
|
401 } |
|
402 |
|
403 CBtmRfcommSock::CBtmRfcommSock(MBtmSockObserver& aObserver, RSocketServ& aServer) |
|
404 : iObserver(&aObserver), iServer(aServer), iInSniff(EFalse) |
|
405 { |
|
406 TRACE_FUNC |
|
407 } |
|
408 |
|
409 // ----------------------------------------------------------------------------- |
|
410 // CBtmAtPipe::HandleAccessoryDataEventL |
|
411 // ----------------------------------------------------------------------------- |
|
412 // |
|
413 void CBtmRfcommSock::SendPacketL() |
|
414 { |
|
415 if (!iWriting && iOutDataQueue && iOutDataQueue->MdcaCount() > 0) |
|
416 { |
|
417 if (iOutData.MaxLength() < iOutDataQueue->MdcaPoint(0).Length()) |
|
418 { |
|
419 iOutData.ReAllocL(iOutDataQueue->MdcaPoint(0).Length()); |
|
420 } |
|
421 iOutData.Copy(iOutDataQueue->MdcaPoint(0)); |
|
422 iDataSocket->Write(iOutData); |
|
423 iOutDataQueue->Delete(0); |
|
424 TRACE_INFO((_L8("[HFP] [O] %S"), &iOutData)) |
|
425 iWriting = ETrue; |
|
426 } |
|
427 } |
|
428 |
|
429 void CBtmRfcommSock::ReceiveL() |
|
430 { |
|
431 TRACE_FUNC |
|
432 TRACE_ASSERT(iDataSocket != NULL, EBTPanicObjectUninitialized) |
|
433 iInData.Zero(); |
|
434 LEAVE_IF_ERROR(iDataSocket->RecvOneOrMore(iInData, 0, iXfrLength)); |
|
435 } |
|
436 |
|
437 void CBtmRfcommSock::CancelReceive() |
|
438 { |
|
439 if (iDataSocket) |
|
440 { |
|
441 TRACE_FUNC_ENTRY |
|
442 iDataSocket->CancelRecv(); |
|
443 TRACE_FUNC_EXIT |
|
444 } |
|
445 } |
|
446 |
|
447 void CBtmRfcommSock::SetService(TUint aService) |
|
448 { |
|
449 iService = aService; |
|
450 } |