1 /* |
|
2 * Copyright (c) 2005 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: An example implementation for ISC Driver Reference |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <kern_priv.h> |
|
22 #include <IscDataTransmissionBase.h> |
|
23 #include "IscChannel.h" |
|
24 #include "IscDevice.h" |
|
25 #include "IscChannelContainer.h" |
|
26 #include "IscQueue.h" |
|
27 #include "IscTrace.h" |
|
28 |
|
29 // EXTERNAL DATA STRUCTURES |
|
30 |
|
31 // EXTERNAL FUNCTION PROTOTYPES |
|
32 |
|
33 // CONSTANTS |
|
34 _LIT( KIscDriver, "IscDriver" ); |
|
35 |
|
36 // MACROS |
|
37 |
|
38 // LOCAL CONSTANTS AND MACROS |
|
39 const TInt KIscInitializeDfcPriority( 1 ); |
|
40 const TInt KOneParam( 1 ); |
|
41 const TInt KTwoParams( 2 ); |
|
42 const TInt KThreeParams( 3 ); |
|
43 const TInt KFirstParam( 0 ); |
|
44 const TInt KSecondParam( 1 ); |
|
45 const TInt KThirdParam( 2 ); |
|
46 const TInt KMultiplyByOne( KSecondParam ); |
|
47 const TInt KMultiplyByThree( KThreeParams ); |
|
48 const TInt KDivideByFour( 4 ); |
|
49 |
|
50 // MODULE DATA STRUCTURES |
|
51 |
|
52 // LOCAL FUNCTION PROTOTYPES |
|
53 |
|
54 // FORWARD DECLARATIONS |
|
55 |
|
56 |
|
57 // ============================ MEMBER FUNCTIONS =============================== |
|
58 |
|
59 |
|
60 // ----------------------------------------------------------------------------- |
|
61 // DIscChannel::DIscChannel |
|
62 // C++ default constructor. |
|
63 // ( other items were commented in a header ). |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 EXPORT_C DIscChannel::DIscChannel( DLogicalDevice* aDevice ) |
|
67 : iInitializeDfc( NULL ), |
|
68 iDataTransmissionIniData( NULL ), |
|
69 iMultiplexerIniData( NULL ), |
|
70 iMultiplexerBuffer( NULL ), |
|
71 iDataTransmissionBuffer( NULL ), |
|
72 iIscDevice( NULL ), |
|
73 iIscConnectionStatusPtr( NULL ), |
|
74 iIscFlowControlStatusPtr( NULL ), |
|
75 iReceiveBufPtr( NULL ), |
|
76 iDataReceiveBufPtr( NULL ), |
|
77 iNeededBufLen( NULL ), |
|
78 iNeededDataBufLen( NULL ), |
|
79 iChannelNumber( 0 ), |
|
80 iChannelOpen( EFalse ), |
|
81 iFrameRx( NULL ), |
|
82 iFrameRxQueue( NULL ), |
|
83 iDataFrameRx( NULL ), |
|
84 iDataFrameRxQueue( NULL ), |
|
85 iULFlowControlStatus( EIscFlowControlOff ), |
|
86 iDLFlowControlStatus( EIscFlowControlOff ), |
|
87 iLastNotifiedULFlowstatus( EIscFlowControlOff ), |
|
88 iIscChannelHighWaterMark( 0 ), |
|
89 iIscChannelLowWaterMark( 0 ), |
|
90 iOverFlow( EFalse ), |
|
91 iClientPanic( EFalse ), |
|
92 iDataTransmissionErrorCode( KErrNone ) |
|
93 { |
|
94 |
|
95 iIscDevice = ( DIscDevice * )aDevice; |
|
96 for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ ) |
|
97 { |
|
98 iIscRequests[i] = NULL; |
|
99 } |
|
100 iThread = &Kern::CurrentThread(); |
|
101 TInt r = iThread->Open(); |
|
102 TRACE_ASSERT( r == KErrNone ); |
|
103 |
|
104 } |
|
105 |
|
106 |
|
107 // ----------------------------------------------------------------------------- |
|
108 // DIscChannel::~DIscChannel |
|
109 // Destructor |
|
110 // ( other items were commented in a header ). |
|
111 // ----------------------------------------------------------------------------- |
|
112 // |
|
113 DIscChannel::~DIscChannel() |
|
114 { |
|
115 C_TRACE( ( _T( "DIscChannel::~DIscChannel()" ) ) ); |
|
116 |
|
117 if ( iChannelNumber < KIscNumberOfUnits ) |
|
118 { |
|
119 IscChannelContainer::RemoveChannel( this ); |
|
120 } |
|
121 else |
|
122 { |
|
123 C_TRACE( ( _T( "DIscChannel::~DIscChannel() re-open" ) ) ); |
|
124 } |
|
125 |
|
126 ChannelDestruction(); |
|
127 Kern::SafeClose( ( DObject*& )iThread, NULL ); |
|
128 C_TRACE( ( _T( "DIscChannel::~DIscChannel() SafeClose called" ) ) ); |
|
129 |
|
130 } |
|
131 |
|
132 // ----------------------------------------------------------------------------- |
|
133 // DIscChannel::ChannelDestruction |
|
134 // Destructor |
|
135 // ( other items were commented in a header ). |
|
136 // ----------------------------------------------------------------------------- |
|
137 // |
|
138 void DIscChannel::ChannelDestruction() |
|
139 { |
|
140 C_TRACE( ( _T( "DIscChannel::ChannelDestruction() iChannelNumber (0x%x)" ),iChannelNumber ) ); |
|
141 |
|
142 // call DIscMultiplexerBase::CloseDLC and DLFlowControlNotify in case the channel has not been |
|
143 // properly closed ( e.g. client thread panic etc. ) |
|
144 if ( iChannelOpen ) |
|
145 { |
|
146 iIscDevice->CancelSending( iChannelNumber, this );// Delete pending send frames |
|
147 iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this ); |
|
148 iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this ); |
|
149 } |
|
150 |
|
151 if ( iFrameRxQueue ) |
|
152 { |
|
153 while ( !iFrameRxQueue->Empty() ) |
|
154 { |
|
155 TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst(); |
|
156 iFrameRxQueue->DeleteFirst(); |
|
157 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
158 } |
|
159 delete iFrameRxQueue; |
|
160 iFrameRxQueue = NULL; |
|
161 } |
|
162 |
|
163 if ( iFrameRx ) |
|
164 { |
|
165 delete [] iFrameRx; |
|
166 iFrameRx = NULL; |
|
167 } |
|
168 |
|
169 if ( iDataFrameRxQueue ) |
|
170 { |
|
171 while ( !iDataFrameRxQueue->Empty() ) |
|
172 { |
|
173 TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst(); |
|
174 iDataFrameRxQueue->DeleteFirst(); |
|
175 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
176 } |
|
177 delete iDataFrameRxQueue; |
|
178 iDataFrameRxQueue = NULL; |
|
179 } |
|
180 |
|
181 if ( iDataFrameRx ) |
|
182 { |
|
183 delete [] iDataFrameRx; |
|
184 iDataFrameRx = NULL; |
|
185 } |
|
186 |
|
187 if ( iInitializeDfc ) |
|
188 { |
|
189 delete iInitializeDfc; |
|
190 iInitializeDfc = NULL; |
|
191 } |
|
192 |
|
193 if ( iDataTransmissionIniData ) |
|
194 { |
|
195 Kern::Free( iDataTransmissionBuffer ); |
|
196 delete iDataTransmissionIniData; |
|
197 iDataTransmissionIniData = NULL; |
|
198 } |
|
199 |
|
200 if ( iMultiplexerIniData ) |
|
201 { |
|
202 Kern::Free( iMultiplexerBuffer ); |
|
203 delete iMultiplexerIniData; |
|
204 iMultiplexerIniData = NULL; |
|
205 } |
|
206 |
|
207 C_TRACE( ( _T( "DIscChannel::ChannelDestruction - return void" ) ) ); |
|
208 } |
|
209 |
|
210 // ----------------------------------------------------------------------------- |
|
211 // DIscChannel::HandleMsg |
|
212 // Message handling ( kernel server context ). |
|
213 // ( other items were commented in a header ). |
|
214 // ----------------------------------------------------------------------------- |
|
215 // |
|
216 void DIscChannel::HandleMsg( |
|
217 TMessageBase* aMsg ) |
|
218 { |
|
219 C_TRACE( ( _T( "DIscChannel::HandleMsg(0x%x)" ), aMsg ) ); |
|
220 TThreadMessage& m=*( TThreadMessage* )aMsg; |
|
221 TInt id( m.iValue ); |
|
222 |
|
223 if ( id==( TInt )ECloseMsg ) |
|
224 { |
|
225 C_TRACE( ( _T( "DIscChannel::HandleMsg ECloseMsg" ) ) ); |
|
226 m.Complete( KErrNone,EFalse ); |
|
227 return; |
|
228 } |
|
229 |
|
230 else if ( id==KMaxTInt ) |
|
231 { |
|
232 // DoCancel |
|
233 // Should not come here ever |
|
234 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoCancel ); |
|
235 } |
|
236 |
|
237 else if ( id<0 ) |
|
238 { |
|
239 // DoRequest |
|
240 // should not come here ever |
|
241 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoRequest ); |
|
242 } |
|
243 |
|
244 else |
|
245 { |
|
246 // DoControl |
|
247 TUint32 a1[ KThreeParams ]; |
|
248 TInt r( KErrNone ); |
|
249 if ( id != EIscSyncClose ) |
|
250 { |
|
251 TInt amountOfParams( KErrNone ); |
|
252 switch( id ) |
|
253 { |
|
254 case EIscAsyncInitializeModemInterface: |
|
255 case EIscAsyncOpen: |
|
256 amountOfParams = KThreeParams; |
|
257 break; |
|
258 default: |
|
259 ASSERT_RESET_ALWAYS( 0, "NokiaISCDriver", EIscUnknownCommand ); |
|
260 break; |
|
261 } |
|
262 r = Kern::ThreadRawRead( iThread, ( TAny* )m.Ptr0(), a1, |
|
263 amountOfParams * sizeof( TAny* ) ); |
|
264 TRACE_ASSERT( r == KErrNone ); |
|
265 } |
|
266 if( r == KErrNone ) |
|
267 { |
|
268 r=HandleRequest( id,a1,m.Ptr1() ); |
|
269 } |
|
270 |
|
271 m.Complete( r,ETrue ); |
|
272 } |
|
273 } |
|
274 |
|
275 // ----------------------------------------------------------------------------- |
|
276 // DIscChannel::Request |
|
277 // Message handling ( user thread context ). |
|
278 // ( other items were commented in a header ). |
|
279 // ----------------------------------------------------------------------------- |
|
280 // |
|
281 #ifndef COMPONENT_TRACE_FLAG |
|
282 TInt DIscChannel::Request( TInt aReqNo, TAny* a1, TAny* ) |
|
283 #else |
|
284 TInt DIscChannel::Request( TInt aReqNo, TAny* a1, TAny* a2) |
|
285 #endif |
|
286 { |
|
287 C_TRACE( ( _T( "DIscChannel::Request(0x%x, 0x%x, 0x%x)" ), aReqNo, a1, a2 ) ); |
|
288 |
|
289 TInt r( KErrNotFound ); |
|
290 |
|
291 if ( aReqNo<( TInt )EMinRequestId ) |
|
292 C_TRACE( ( _T( "DIscChannel::Request ERROR: False aReqNo %d" ), aReqNo ) ); |
|
293 |
|
294 if ( aReqNo >= 0 && aReqNo < EIscAsyncLastKernelServerContext || |
|
295 aReqNo >= EIscAsyncLast && aReqNo < EIscSyncLastKernelServerContext ) |
|
296 { |
|
297 TThreadMessage& m=Kern::Message(); |
|
298 m.iValue=aReqNo; |
|
299 m.iArg[ KFirstParam ]=a1; |
|
300 m.iArg[ KSecondParam ]=NULL; |
|
301 r = m.SendReceive( &iMsgQ ); |
|
302 } |
|
303 else |
|
304 { |
|
305 TInt ulen( KErrNotFound ); |
|
306 switch ( aReqNo ) |
|
307 { |
|
308 case EIscCancelAsyncInitialize: |
|
309 case EIscCancelAsyncReceive: |
|
310 case EIscCancelAsyncDataReceive: |
|
311 case EIscSyncGetConnectionStatus: |
|
312 case EIscCancelAsyncNotifyConnection: |
|
313 case EIscSyncGetFlowControlStatus: |
|
314 case EIscCancelAsyncNotifyFlowControl: |
|
315 case EIscSyncGetMaximunDataSize: |
|
316 case EIscCancelAsyncCustomOperation1: |
|
317 case EIscCancelAsyncCustomOperation2: |
|
318 case EIscCancelAsyncCustomOperation3: |
|
319 case EIscCancelAsyncCustomOperation4: |
|
320 case EIscCancelAsyncCustomOperation5: |
|
321 case EIscCancelAsyncOpen: |
|
322 case EIscSyncResetBuffers: |
|
323 case EIscCancelAsyncSend: |
|
324 case EIscCancelAsyncDataSend: |
|
325 { |
|
326 ulen = KErrNone; |
|
327 break; |
|
328 } |
|
329 case EIscSyncSend: |
|
330 case EIscSyncDataSend: |
|
331 case EIscSyncCustomOperation1: |
|
332 case EIscSyncCustomOperation2: |
|
333 case EIscSyncCustomOperation3: |
|
334 case EIscSyncCustomOperation4: |
|
335 case EIscSyncCustomOperation5: |
|
336 case EIscAsyncClose: |
|
337 { |
|
338 ulen = KOneParam; |
|
339 break; |
|
340 } |
|
341 case EIscAsyncSend: |
|
342 case EIscAsyncDataSend: |
|
343 case EIscSyncGetChannelInfo: |
|
344 case EIscAsyncNotifyConnectionStatus: |
|
345 case EIscAsyncNotifyFlowControlStatus: |
|
346 case EIscAsyncCustomOperation1: |
|
347 case EIscAsyncCustomOperation2: |
|
348 case EIscAsyncCustomOperation3: |
|
349 case EIscAsyncCustomOperation4: |
|
350 case EIscAsyncCustomOperation5: |
|
351 { |
|
352 ulen = KTwoParams; |
|
353 break; |
|
354 } |
|
355 case EIscAsyncReceive: |
|
356 case EIscAsyncDataReceive: |
|
357 { |
|
358 ulen = KThreeParams; |
|
359 break; |
|
360 } |
|
361 default: |
|
362 { |
|
363 TRACE_ASSERT_ALWAYS; |
|
364 } |
|
365 } |
|
366 ASSERT_RESET_ALWAYS( KErrNotFound != ulen, "ISCDriver", EIscUnknownCommand ); |
|
367 // Maximum number of elements is three!!! |
|
368 TAny* kptr[ KThreeParams ] = { KErrNone }; |
|
369 if( ulen > KErrNone ) |
|
370 { |
|
371 C_TRACE( ( _T( "DIscChannel::Request ISC kumemget32" ) ) ); |
|
372 kumemget32( kptr , a1, ( sizeof( TAny* ) ) * ulen ); |
|
373 } |
|
374 r = HandleRequest( aReqNo, kptr, NULL ); |
|
375 } |
|
376 C_TRACE( ( _T( "DIscChannel::Request ISC return %d CH 0x%x" ), r, iChannelNumber ) ); |
|
377 return r; |
|
378 |
|
379 } |
|
380 |
|
381 // ----------------------------------------------------------------------------- |
|
382 // DIscChannel::DoControl |
|
383 // Handles requests. |
|
384 // ( other items were commented in a header ). |
|
385 // ----------------------------------------------------------------------------- |
|
386 // |
|
387 TInt DIscChannel::HandleRequest( |
|
388 TInt aFunction, |
|
389 TAny* a1, |
|
390 TAny* /*a2*/ ) |
|
391 { |
|
392 C_TRACE( ( _T( "DIscChannel::DoControl(0x%x, 0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aFunction, a1, iChannelNumber, this ) ); |
|
393 |
|
394 TInt error( KErrNone ); |
|
395 |
|
396 #ifdef _DEBUG |
|
397 // Check if control frame buffer overflow -> panic |
|
398 if ( iClientPanic ) |
|
399 { |
|
400 C_TRACE( ( _T( "DIscChannel::DoControl() BUFFER OVERFLOW: PANIC CLIENT 0x%x" ), iChannelNumber ) ); |
|
401 TRACE_ASSERT_ALWAYS; |
|
402 // This panic the user thread only. |
|
403 Kern::ThreadKill( iThread, EExitPanic, EIscControlBufferOverflow, KIscDriver ); |
|
404 } |
|
405 #endif // _DEBUG |
|
406 |
|
407 // Handle asynchronous requests |
|
408 if ( aFunction >= EIscAsyncInitializeModemInterface && |
|
409 aFunction < EIscAsyncLast ) |
|
410 { |
|
411 // if request is already active |
|
412 if ( iIscRequests[aFunction] ) |
|
413 { |
|
414 TUint32* tablePtr = ( TUint32* )a1; |
|
415 TRequestStatus* requestStatus = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
416 Kern::RequestComplete( iThread, requestStatus, KErrAlreadyExists ); |
|
417 } |
|
418 else |
|
419 { |
|
420 HandleAsyncRequest( aFunction, a1 ); |
|
421 } |
|
422 } |
|
423 // Handle synchronous requests. |
|
424 else if ( aFunction >= EIscAsyncLast && |
|
425 aFunction < EIscSyncLast ) |
|
426 { |
|
427 error = HandleSyncRequest( aFunction, a1 ); |
|
428 } |
|
429 // Handle cancellation requests. |
|
430 else if ( aFunction >= EIscSyncLast && |
|
431 aFunction < EIscCancelLast ) |
|
432 { |
|
433 error = HandleCancelRequest( aFunction, a1 ); |
|
434 } |
|
435 // Undefined request, panic current thread. |
|
436 else |
|
437 { |
|
438 // This panic the user thread only. |
|
439 Kern::ThreadKill( iThread, EExitPanic, EIscControlBufferOverflow, KIscDriver ); |
|
440 } |
|
441 |
|
442 C_TRACE( ( _T( "DIscChannel::DoControl - return %d" ), error ) ); |
|
443 |
|
444 return error; |
|
445 } |
|
446 |
|
447 |
|
448 // ----------------------------------------------------------------------------- |
|
449 // DIscChannel::HandleAsyncRequests |
|
450 // Handles asynchronous client requests |
|
451 // ( other items were commented in a header ). |
|
452 // ----------------------------------------------------------------------------- |
|
453 // |
|
454 void DIscChannel::HandleAsyncRequest( |
|
455 TInt aFunction, |
|
456 TAny* a1 ) |
|
457 { |
|
458 C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest(0x%x, 0x%x) channelPtr 0x%x" ), aFunction, a1, this ) ); |
|
459 |
|
460 TUint32* tablePtr = ( TUint32* )a1; |
|
461 |
|
462 switch ( aFunction ) |
|
463 { |
|
464 case EIscAsyncInitializeModemInterface: |
|
465 { |
|
466 TInt r = KErrNotFound; |
|
467 iIscRequests[EIscAsyncInitializeModemInterface] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
468 |
|
469 iInitializeDfc = new TDfc( InitializeComplete, this, Kern::DfcQue0(), KIscInitializeDfcPriority ); |
|
470 ASSERT_RESET_ALWAYS( iInitializeDfc, "IscDriver",EIscMemoryAllocationFailure ); |
|
471 |
|
472 // Get Data Transmission Driver initialization string |
|
473 TDesC8* tempPtr = ( TDesC8* )tablePtr[ KThirdParam ]; |
|
474 iDataTransmissionBuffer = ( TUint8* )Kern::Alloc( KIscIniLineLength ); |
|
475 ASSERT_RESET_ALWAYS( iDataTransmissionBuffer, "IscDriver",EIscMemoryAllocationFailure ); |
|
476 |
|
477 iDataTransmissionIniData = new ( TPtr8 )( iDataTransmissionBuffer, KIscIniLineLength ); |
|
478 ASSERT_RESET_ALWAYS( iDataTransmissionIniData, "IscDriver",EIscMemoryAllocationFailure ); |
|
479 |
|
480 r = Kern::ThreadDesRead( iThread, tempPtr, *iDataTransmissionIniData, 0, KChunkShiftBy0 ); |
|
481 ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure ); |
|
482 |
|
483 // Get Multiplexer initialization string |
|
484 tempPtr = ( TDesC8* )tablePtr[1]; |
|
485 iMultiplexerBuffer = ( TUint8* )Kern::Alloc( KIscIniLineLength ); |
|
486 ASSERT_RESET_ALWAYS( iMultiplexerBuffer, "IscDriver",EIscMemoryAllocationFailure ); |
|
487 |
|
488 iMultiplexerIniData = new ( TPtr8 )( iMultiplexerBuffer, KIscIniLineLength ); |
|
489 ASSERT_RESET_ALWAYS( iDataTransmissionIniData, "IscDriver",EIscMemoryAllocationFailure ); |
|
490 |
|
491 r = Kern::ThreadDesRead( iThread, tempPtr, *iMultiplexerIniData, 0, KChunkShiftBy0 ); |
|
492 ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure ); |
|
493 |
|
494 // If buffer configuration is given from isc_config.ini as multiplexer configuration string, multiplexer |
|
495 // needs configuration before datatransmissin driver is initialized |
|
496 iIscDevice->iIscMultiplexerInterface->SetInitializationParameters( *iMultiplexerIniData ); |
|
497 |
|
498 // Allocate buffers and receive queues |
|
499 iIscDevice->Initialize(); |
|
500 |
|
501 iIscDevice->iIscDataTransmissionInterface->InitializeDataTransmission( *iDataTransmissionIniData, |
|
502 iInitializeDfc, |
|
503 iDataTransmissionErrorCode ); |
|
504 break; |
|
505 } |
|
506 |
|
507 case EIscAsyncOpen: |
|
508 { |
|
509 iIscRequests[EIscAsyncOpen] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
510 if ( iIscDevice->ConnectionStatus() == EIscConnectionOk ) |
|
511 { |
|
512 TDesC8* openInfo = ( TDesC8* )tablePtr[ KThirdParam ]; |
|
513 // Channel info parameter has to be copied from user side in Epoc Kernel Architecture 2 |
|
514 TInt length = Kern::ThreadGetDesLength( iThread, ( TDesC8* )tablePtr[ KThirdParam ] ); |
|
515 TUint8* buffer = NULL; |
|
516 TPtr8* bufferPtr = NULL; |
|
517 if ( length > KErrNone ) |
|
518 { |
|
519 C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest EIscAsyncOpen channel info got" ) ) ); |
|
520 buffer = ( TUint8* )Kern::Alloc( length ); |
|
521 bufferPtr = new ( TPtr8 )( buffer, length ); |
|
522 TInt r = Kern::ThreadDesRead( iThread, openInfo, *bufferPtr, 0, KChunkShiftBy0 ); |
|
523 ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure ); |
|
524 openInfo = ( TDesC8* )bufferPtr; |
|
525 } |
|
526 iIscDevice->iIscMultiplexerInterface->OpenDLC( ( TUint16 )tablePtr[ KSecondParam ], |
|
527 openInfo, |
|
528 this ); |
|
529 |
|
530 if ( buffer ) |
|
531 Kern::Free( buffer ); |
|
532 if ( bufferPtr ) |
|
533 { |
|
534 delete bufferPtr; |
|
535 bufferPtr = NULL; |
|
536 } |
|
537 } |
|
538 else |
|
539 { |
|
540 CompleteRequest( aFunction, KErrNotReady ); |
|
541 } |
|
542 break; |
|
543 } |
|
544 case EIscAsyncSend: |
|
545 { |
|
546 iIscRequests[EIscAsyncSend] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
547 if ( iIscDevice->ConnectionStatus() == EIscConnectionOk |
|
548 && iULFlowControlStatus == EIscFlowControlOff ) |
|
549 { |
|
550 TDesC8* ptr = ( TDesC8* ) tablePtr[ KSecondParam ]; |
|
551 |
|
552 // No return values check needed. Request completed with error value by multiplexer |
|
553 iIscDevice->iIscMultiplexerInterface->Send( ( TUint16 )aFunction, |
|
554 iChannelNumber, |
|
555 *ptr, |
|
556 this ); |
|
557 } |
|
558 else |
|
559 { |
|
560 if ( iULFlowControlStatus != EIscFlowControlOff ) |
|
561 { |
|
562 CompleteRequest( aFunction, KErrOverflow ); |
|
563 } |
|
564 else |
|
565 { |
|
566 CompleteRequest( aFunction, KErrNotReady ); |
|
567 } |
|
568 } |
|
569 break; |
|
570 } |
|
571 case EIscAsyncReceive: |
|
572 { |
|
573 TRACE_ASSERT( tablePtr[ KFirstParam ] ); |
|
574 TRACE_ASSERT( tablePtr[ KSecondParam ] ); |
|
575 TRACE_ASSERT( tablePtr[ KThirdParam ] ); |
|
576 |
|
577 // check for descriptor validity |
|
578 TRACE_ASSERT( Kern::ThreadGetDesMaxLength( iThread, (TPtr8* )tablePtr[KSecondParam] ) > 0 ); |
|
579 |
|
580 //Store needed length ptr |
|
581 iNeededBufLen = ( TPtr8* )tablePtr[ KThirdParam ]; |
|
582 |
|
583 //Store msg data ptr |
|
584 iReceiveBufPtr = ( TPtr8* )tablePtr[ KSecondParam ]; |
|
585 |
|
586 iIscRequests[EIscAsyncReceive] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
587 |
|
588 break; |
|
589 } |
|
590 case EIscAsyncDataSend: |
|
591 { |
|
592 iIscRequests[EIscAsyncDataSend] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
593 |
|
594 if ( iIscDevice->ConnectionStatus() == EIscConnectionOk |
|
595 && iULFlowControlStatus == EIscFlowControlOff ) |
|
596 { |
|
597 TDesC8* ptr = ( TDesC8* )tablePtr[ KSecondParam ]; |
|
598 iIscDevice->iIscMultiplexerInterface->DataSend( ( TUint16 )aFunction, |
|
599 iChannelNumber, |
|
600 *ptr, |
|
601 this ); |
|
602 } |
|
603 else |
|
604 { |
|
605 if ( iULFlowControlStatus != EIscFlowControlOff ) |
|
606 { |
|
607 CompleteRequest( aFunction, KErrOverflow ); |
|
608 } |
|
609 else |
|
610 { |
|
611 CompleteRequest( aFunction, KErrNotReady ); |
|
612 } |
|
613 } |
|
614 break; |
|
615 } |
|
616 case EIscAsyncDataReceive: |
|
617 { |
|
618 TRACE_ASSERT( tablePtr[ KFirstParam ] ); |
|
619 TRACE_ASSERT( tablePtr[ KSecondParam ] ); |
|
620 TRACE_ASSERT( tablePtr[ KThirdParam ] ); |
|
621 |
|
622 // check for descriptor validity |
|
623 TRACE_ASSERT( Kern::ThreadGetDesMaxLength( iThread, (TPtr8* )tablePtr[KSecondParam] ) > 0 ); |
|
624 |
|
625 //Store needed length ptr |
|
626 iNeededDataBufLen = ( TPtr8* )tablePtr[ KThirdParam ]; |
|
627 |
|
628 //Store msg data ptr |
|
629 iDataReceiveBufPtr = ( TPtr8* )tablePtr[ KSecondParam ]; |
|
630 |
|
631 iIscRequests[EIscAsyncDataReceive] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
632 |
|
633 break; |
|
634 } |
|
635 case EIscAsyncNotifyConnectionStatus: |
|
636 { |
|
637 iIscConnectionStatusPtr = ( TPtr8* )tablePtr[ KSecondParam ]; |
|
638 iIscRequests[EIscAsyncNotifyConnectionStatus] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
639 break; |
|
640 } |
|
641 case EIscAsyncNotifyFlowControlStatus: |
|
642 { |
|
643 iIscFlowControlStatusPtr = reinterpret_cast<TPtr8*>( tablePtr[ KSecondParam ] ); |
|
644 iIscRequests[ EIscAsyncNotifyFlowControlStatus ] = reinterpret_cast<TRequestStatus*>( tablePtr[ KFirstParam ] ); |
|
645 C_TRACE( ( _T( "DIscChannel::NotifyFlowControl iLastNotifiedULFlowstatus = %d iULFlowControlStatus = %d" ), iLastNotifiedULFlowstatus, iULFlowControlStatus ) ); |
|
646 |
|
647 if( iULFlowControlStatus != iLastNotifiedULFlowstatus ) |
|
648 { |
|
649 // Complete immediately. |
|
650 C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest iULFlowControlStatus != iLastNotifiedULFlowstatus" ) ) ); |
|
651 NotifyFlowControl( iULFlowControlStatus ); |
|
652 } |
|
653 else |
|
654 { |
|
655 // None |
|
656 } |
|
657 break; |
|
658 } |
|
659 case EIscAsyncCustomOperation1: |
|
660 case EIscAsyncCustomOperation2: |
|
661 case EIscAsyncCustomOperation3: |
|
662 case EIscAsyncCustomOperation4: |
|
663 case EIscAsyncCustomOperation5: |
|
664 { |
|
665 iIscRequests[aFunction] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
666 TAny* tempPtr = ( TAny* )tablePtr[ KSecondParam ]; |
|
667 iIscDevice->iIscMultiplexerInterface->CustomFunction( iChannelNumber, |
|
668 ( TUint16 )aFunction, |
|
669 tempPtr, |
|
670 this ); |
|
671 break; |
|
672 } |
|
673 case EIscAsyncClose: |
|
674 { |
|
675 iIscRequests[aFunction] = ( TRequestStatus* )( tablePtr[ KFirstParam ] ); |
|
676 |
|
677 ResetBuffers(); |
|
678 |
|
679 // Cancel all active requests except asynchronous close |
|
680 for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ ) |
|
681 { |
|
682 // if request is active complete it with KErrCancel |
|
683 if ( iIscRequests[i] && i != EIscAsyncClose ) |
|
684 { |
|
685 iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, i, this ); |
|
686 CompleteRequest( i, KErrCancel ); |
|
687 } |
|
688 } |
|
689 |
|
690 iChannelOpen = EFalse; |
|
691 |
|
692 iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this ); |
|
693 |
|
694 break; |
|
695 } |
|
696 default: |
|
697 { |
|
698 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand ); |
|
699 break; |
|
700 } |
|
701 } |
|
702 |
|
703 IscChannelContainer::AddDfc(); |
|
704 |
|
705 } |
|
706 |
|
707 |
|
708 // ----------------------------------------------------------------------------- |
|
709 // DIscChannel::HandleSyncRequest |
|
710 // Handles synchronous client requests |
|
711 // ( other items were commented in a header ). |
|
712 // ----------------------------------------------------------------------------- |
|
713 // |
|
714 TInt DIscChannel::HandleSyncRequest( |
|
715 TInt aFunction, |
|
716 TAny* a1 ) |
|
717 { |
|
718 C_TRACE( ( _T( "DIscChannel::HandleSyncRequest(0x%x, 0x%x) channelPtr 0x%x" ), aFunction, a1, this ) ); |
|
719 |
|
720 TInt error( KErrNone ); |
|
721 TUint32* tablePtr = ( TUint32* )a1; |
|
722 |
|
723 switch ( aFunction ) |
|
724 { |
|
725 case EIscSyncClose: |
|
726 { |
|
727 ResetBuffers(); |
|
728 |
|
729 iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this ); |
|
730 |
|
731 // Cancel all active requests |
|
732 for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ ) |
|
733 { |
|
734 // if request is active complete it with KErrCancel |
|
735 if ( iIscRequests[i] ) |
|
736 { |
|
737 iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, i, this ); |
|
738 CompleteRequest( i, KErrCancel ); |
|
739 } |
|
740 } |
|
741 |
|
742 error = KErrNone; |
|
743 iChannelOpen = EFalse; |
|
744 break; |
|
745 } |
|
746 case EIscSyncSend: |
|
747 { |
|
748 if ( iIscDevice->ConnectionStatus() == EIscConnectionOk |
|
749 && iULFlowControlStatus == EIscFlowControlOff ) |
|
750 { |
|
751 |
|
752 TDesC8* ptr = ( TDesC8* ) tablePtr[ KFirstParam ]; |
|
753 error = iIscDevice->iIscMultiplexerInterface->Send( ( TUint16 )aFunction, |
|
754 iChannelNumber, |
|
755 *ptr, |
|
756 this ); |
|
757 } |
|
758 else |
|
759 { |
|
760 if ( iULFlowControlStatus != EIscFlowControlOff ) |
|
761 { |
|
762 error = KErrOverflow; |
|
763 } |
|
764 else |
|
765 { |
|
766 error = KErrNotReady; |
|
767 } |
|
768 } |
|
769 break; |
|
770 } |
|
771 case EIscSyncDataSend: |
|
772 { |
|
773 if ( iIscDevice->ConnectionStatus() == EIscConnectionOk |
|
774 && iULFlowControlStatus == EIscFlowControlOff ) |
|
775 { |
|
776 TDesC8* ptr = ( TDesC8* ) tablePtr[ KFirstParam ]; |
|
777 error = iIscDevice->iIscMultiplexerInterface->DataSend( ( TUint16 )aFunction, |
|
778 iChannelNumber, |
|
779 *ptr, |
|
780 this ); |
|
781 } |
|
782 else |
|
783 { |
|
784 if ( iULFlowControlStatus != EIscFlowControlOff ) |
|
785 { |
|
786 error = KErrOverflow; |
|
787 } |
|
788 else |
|
789 { |
|
790 error = KErrNotReady; |
|
791 } |
|
792 } |
|
793 break; |
|
794 } |
|
795 case EIscSyncGetConnectionStatus: |
|
796 { |
|
797 error = iIscDevice->ConnectionStatus(); |
|
798 break; |
|
799 } |
|
800 case EIscSyncGetFlowControlStatus: |
|
801 { |
|
802 error = iULFlowControlStatus; |
|
803 break; |
|
804 } |
|
805 case EIscSyncGetChannelInfo: |
|
806 { |
|
807 TDes8* tempPtr = ( TDes8* ) tablePtr[1]; |
|
808 error = iIscDevice->iIscMultiplexerInterface->GetChannelInfo( ( TUint16 )tablePtr[ KFirstParam ], |
|
809 *tempPtr ); |
|
810 break; |
|
811 } |
|
812 case EIscSyncGetMaximunDataSize: |
|
813 { |
|
814 error = iIscDevice->iIscMultiplexerInterface->MaximumDataSize( iChannelNumber ); |
|
815 break; |
|
816 } |
|
817 case EIscSyncCustomOperation1: |
|
818 case EIscSyncCustomOperation2: |
|
819 case EIscSyncCustomOperation3: |
|
820 case EIscSyncCustomOperation4: |
|
821 case EIscSyncCustomOperation5: |
|
822 { |
|
823 TAny* tempPtr = ( TAny* )tablePtr[ KFirstParam ]; |
|
824 error = iIscDevice->iIscMultiplexerInterface->CustomFunction( iChannelNumber, |
|
825 ( TUint16 )aFunction, |
|
826 tempPtr, |
|
827 this ); |
|
828 break; |
|
829 } |
|
830 case EIscSyncResetBuffers: |
|
831 { |
|
832 ResetBuffers(); |
|
833 error = KErrNone; |
|
834 break; |
|
835 } |
|
836 default: |
|
837 { |
|
838 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand ); |
|
839 break; |
|
840 } |
|
841 } |
|
842 return error; |
|
843 } |
|
844 |
|
845 // ----------------------------------------------------------------------------- |
|
846 // DIscChannel::HandleCancelRequest |
|
847 // Cancels active request |
|
848 // ( other items were commented in a header ). |
|
849 // ----------------------------------------------------------------------------- |
|
850 // |
|
851 TInt DIscChannel::HandleCancelRequest( |
|
852 TInt aFunction, |
|
853 TAny* /*a1*/ ) |
|
854 { |
|
855 C_TRACE( ( _T( "DIscChannel::HandleCancelRequest(0x%x)" ), aFunction ) ); |
|
856 |
|
857 TUint16 operationToCancel( 0 ); |
|
858 switch ( aFunction ) |
|
859 { |
|
860 |
|
861 case EIscCancelAsyncInitialize: |
|
862 { |
|
863 if ( iDataTransmissionIniData ) |
|
864 { |
|
865 Kern::Free( iDataTransmissionBuffer ); |
|
866 delete iDataTransmissionIniData; |
|
867 iDataTransmissionIniData = NULL; |
|
868 } |
|
869 if ( iMultiplexerIniData ) |
|
870 { |
|
871 Kern::Free( iMultiplexerBuffer ); |
|
872 delete iMultiplexerIniData; |
|
873 iMultiplexerIniData = NULL; |
|
874 } |
|
875 |
|
876 operationToCancel = EIscAsyncInitializeModemInterface; |
|
877 break; |
|
878 } |
|
879 case EIscCancelAsyncOpen: |
|
880 { |
|
881 if ( KRequestPending == IsPending( EIscAsyncOpen ) ) |
|
882 { |
|
883 iChannelOpen = EFalse; |
|
884 } |
|
885 operationToCancel = EIscAsyncOpen; |
|
886 break; |
|
887 } |
|
888 case EIscCancelAsyncSend: |
|
889 { |
|
890 operationToCancel = EIscAsyncSend; |
|
891 // Cancel sending / empty send queues |
|
892 iIscDevice->CancelSending( iChannelNumber, this ); |
|
893 break; |
|
894 } |
|
895 case EIscCancelAsyncDataSend: |
|
896 { |
|
897 operationToCancel = EIscAsyncDataSend; |
|
898 // Cancel sending / empty send queues |
|
899 iIscDevice->CancelSending( iChannelNumber, this ); |
|
900 break; |
|
901 } |
|
902 |
|
903 case EIscCancelAsyncReceive: |
|
904 { |
|
905 iReceiveBufPtr = NULL; |
|
906 iNeededBufLen = NULL; |
|
907 operationToCancel = EIscAsyncReceive; |
|
908 break; |
|
909 } |
|
910 |
|
911 case EIscCancelAsyncDataReceive: |
|
912 { |
|
913 iDataReceiveBufPtr = NULL; |
|
914 iNeededDataBufLen = NULL; |
|
915 operationToCancel = EIscAsyncDataReceive; |
|
916 break; |
|
917 } |
|
918 |
|
919 case EIscCancelAsyncNotifyConnection: |
|
920 { |
|
921 iIscConnectionStatusPtr = NULL; |
|
922 operationToCancel = EIscAsyncNotifyConnectionStatus; |
|
923 break; |
|
924 } |
|
925 |
|
926 case EIscCancelAsyncNotifyFlowControl: |
|
927 { |
|
928 iIscFlowControlStatusPtr = NULL; |
|
929 operationToCancel = EIscAsyncNotifyFlowControlStatus; |
|
930 break; |
|
931 } |
|
932 case EIscCancelAsyncCustomOperation1: |
|
933 { |
|
934 operationToCancel = EIscAsyncCustomOperation1; |
|
935 break; |
|
936 } |
|
937 case EIscCancelAsyncCustomOperation2: |
|
938 { |
|
939 operationToCancel = EIscAsyncCustomOperation2; |
|
940 break; |
|
941 } |
|
942 case EIscCancelAsyncCustomOperation3: |
|
943 { |
|
944 operationToCancel = EIscAsyncCustomOperation3; |
|
945 break; |
|
946 } |
|
947 case EIscCancelAsyncCustomOperation4: |
|
948 { |
|
949 operationToCancel = EIscAsyncCustomOperation4; |
|
950 break; |
|
951 } |
|
952 case EIscCancelAsyncCustomOperation5: |
|
953 { |
|
954 operationToCancel = EIscAsyncCustomOperation5; |
|
955 break; |
|
956 } |
|
957 case EIscCancelAsyncClose: |
|
958 { |
|
959 TRACE_ASSERT_ALWAYS; |
|
960 operationToCancel = EIscAsyncClose; |
|
961 break; |
|
962 } |
|
963 default: |
|
964 { |
|
965 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand ); |
|
966 break; |
|
967 } |
|
968 } |
|
969 |
|
970 iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, ( TUint16 )operationToCancel, this ); |
|
971 CompleteRequest( operationToCancel, KErrCancel ); |
|
972 |
|
973 return KErrNone; |
|
974 } |
|
975 |
|
976 // ----------------------------------------------------------------------------- |
|
977 // DIscChannel::DoCreate |
|
978 // Secondary initialization of channel |
|
979 // ( other items were commented in a header ). |
|
980 // ----------------------------------------------------------------------------- |
|
981 // |
|
982 TInt DIscChannel::DoCreate( |
|
983 TInt aUnit, |
|
984 const TDesC8* anInfo, |
|
985 const TVersion& /*aVer*/ ) |
|
986 { |
|
987 C_TRACE( ( _T( "DIscChannel::DoCreate(0x%x, 0x%x, 0x%x)" ), aUnit, anInfo, this ) ); |
|
988 if ( !Kern::CurrentThreadHasCapability( ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING |
|
989 ( "Checked by ISCDRIVER.LDD ( Inter-System Communication Driver )" ) ) ) |
|
990 { |
|
991 return KErrPermissionDenied; |
|
992 } |
|
993 TUint16 channelNumber = ( TUint16 )aUnit; |
|
994 if ( anInfo ) |
|
995 { |
|
996 // check for channel number inside anInfo |
|
997 TUint8 channel = ( TUint8 )( *anInfo )[0]; |
|
998 if ( channel >= KIscMaxChannelsInLdd ) |
|
999 { |
|
1000 channelNumber += KIscMaxChannelsInLdd; |
|
1001 } |
|
1002 C_TRACE( ( _T( "DIscChannel::DoCreate channel=0x%x" ), channelNumber ) ); |
|
1003 } |
|
1004 |
|
1005 if ( channelNumber != KIscControlChannel ) |
|
1006 { |
|
1007 TIscConfiguration config; |
|
1008 iIscDevice->iIscMultiplexerInterface->GetConfiguration( config ); |
|
1009 TInt i( KErrNone ); |
|
1010 iFrameRx = new TUint32*[config.channelRcvQueueSize]; |
|
1011 ASSERT_RESET_ALWAYS( iFrameRx, "IscDriver",EIscMemoryAllocationFailure ); |
|
1012 for ( i = KErrNone; i < config.channelRcvQueueSize; i++ ) |
|
1013 { |
|
1014 iFrameRx[i] = 0; |
|
1015 } |
|
1016 |
|
1017 iDataFrameRx = new TUint32*[config.channelDataRcvQueueSize]; |
|
1018 ASSERT_RESET_ALWAYS( iDataFrameRx, "IscDriver",EIscMemoryAllocationFailure ); |
|
1019 for ( i = KErrNone; i < config.channelDataRcvQueueSize; i++ ) |
|
1020 { |
|
1021 iDataFrameRx[i] = 0; |
|
1022 } |
|
1023 |
|
1024 // creating frame queue for incoming frames |
|
1025 iFrameRxQueue = new DIscQueue( iFrameRx, config.channelRcvQueueSize ); |
|
1026 ASSERT_RESET_ALWAYS( iFrameRxQueue, "IscDriver",EIscMemoryAllocationFailure ); |
|
1027 |
|
1028 // creating frame queue for incoming data frames |
|
1029 iDataFrameRxQueue = new DIscQueue( iDataFrameRx, config.channelDataRcvQueueSize ); |
|
1030 ASSERT_RESET_ALWAYS( iDataFrameRxQueue, "IscDriver",EIscMemoryAllocationFailure ); |
|
1031 |
|
1032 // Flowcontrol marks for data frames |
|
1033 iIscChannelHighWaterMark = ( TUint16 )( ( ( ( TUint16 )config.channelDataRcvQueueSize ) * KMultiplyByThree ) / KDivideByFour );// 75% = multiply with 3, divide by 4 |
|
1034 iIscChannelLowWaterMark = ( TUint16 )( ( ( ( TUint16 )config.channelDataRcvQueueSize ) * KMultiplyByOne ) / KDivideByFour );// 25% = multiply with 1, divide by 4 |
|
1035 |
|
1036 TRACE_ASSERT( iIscChannelHighWaterMark != 0 ); |
|
1037 } |
|
1038 |
|
1039 #ifndef ISC_CHANNEL_SHARING_IN_USE |
|
1040 // Remove checking if channel already set to enable channel sharing |
|
1041 //Check if channel already set |
|
1042 if ( IscChannelContainer::Channel( channelNumber, 0 ) ) |
|
1043 { |
|
1044 C_TRACE( ( _T( "DIscChannel::DoCreate channel 0x%x already set!!!!" ), channelNumber ) ); |
|
1045 return KErrAlreadyExists; |
|
1046 } |
|
1047 #endif //ISC_CHANNEL_SHARING_IN_USE |
|
1048 |
|
1049 //Add itself to channel table. |
|
1050 TInt error = IscChannelContainer::SetChannel( ( DIscChannel* )this, channelNumber ); |
|
1051 if ( KErrNone != error ) |
|
1052 { |
|
1053 return error; |
|
1054 } |
|
1055 |
|
1056 iChannelOpen = ETrue; |
|
1057 |
|
1058 // Store channel number. |
|
1059 iChannelNumber = channelNumber; |
|
1060 SetDfcQ( Kern::DfcQue0() ); |
|
1061 iMsgQ.Receive(); |
|
1062 |
|
1063 return KErrNone; |
|
1064 |
|
1065 } |
|
1066 |
|
1067 |
|
1068 // ----------------------------------------------------------------------------- |
|
1069 // DIscChannel::NotifyFlowControl |
|
1070 // Notify user side client that uplink flow control is on/off |
|
1071 // ( other items were commented in a header ). |
|
1072 // ----------------------------------------------------------------------------- |
|
1073 // |
|
1074 void DIscChannel::NotifyFlowControl |
|
1075 ( |
|
1076 const TInt aFlowControlStatus |
|
1077 ) |
|
1078 { |
|
1079 C_TRACE( ( _T( "DIscChannel::NotifyFlowControl(0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aFlowControlStatus, iChannelNumber, this ) ); |
|
1080 |
|
1081 iULFlowControlStatus = aFlowControlStatus; |
|
1082 if( iIscRequests[ EIscAsyncNotifyFlowControlStatus ] |
|
1083 && iIscFlowControlStatusPtr ) |
|
1084 { |
|
1085 TPtr8 tempDes( reinterpret_cast<TUint8*>( &iULFlowControlStatus ), sizeof ( TInt ), sizeof ( TInt ) ); |
|
1086 iLastNotifiedULFlowstatus = aFlowControlStatus; |
|
1087 TInt r = ThreadWrite( static_cast<TAny*>( iIscFlowControlStatusPtr ), &tempDes, 0 ); |
|
1088 TRACE_ASSERT( r == KErrNone ); |
|
1089 CompleteRequest( EIscAsyncNotifyFlowControlStatus, r ); |
|
1090 } |
|
1091 else |
|
1092 { |
|
1093 C_TRACE( ( _T( "DIscChannel::NotifyFlowControl No request pending!" ) ) ); |
|
1094 } |
|
1095 } |
|
1096 |
|
1097 // ----------------------------------------------------------------------------- |
|
1098 // DIscChannel::NotifyConnectionStatus |
|
1099 // Notify user side client that connection status has changed |
|
1100 // ( other items were commented in a header ). |
|
1101 // ----------------------------------------------------------------------------- |
|
1102 // |
|
1103 void DIscChannel::NotifyConnectionStatus( |
|
1104 const TInt aConnectionStatus ) |
|
1105 { |
|
1106 C_TRACE( ( _T( "DIscChannel::NotifyConnectionStatus(0x%x) channelPtr 0x%x" ), aConnectionStatus, this ) ); |
|
1107 |
|
1108 if ( iIscRequests[EIscAsyncNotifyConnectionStatus] |
|
1109 && iIscConnectionStatusPtr ) |
|
1110 { |
|
1111 TInt temp = aConnectionStatus; |
|
1112 TPtr8 tempDes( ( TUint8* )&temp,sizeof ( TInt ),sizeof ( TInt ) ); |
|
1113 TInt r = ThreadWrite( ( TAny* )iIscConnectionStatusPtr, &tempDes, 0 ); |
|
1114 TRACE_ASSERT( r == KErrNone ); |
|
1115 |
|
1116 CompleteRequest( EIscAsyncNotifyConnectionStatus, r ); |
|
1117 } |
|
1118 } |
|
1119 |
|
1120 // ----------------------------------------------------------------------------- |
|
1121 // DIscChannel::IsPending |
|
1122 // Check if asynchronous request is active |
|
1123 // ( other items were commented in a header ). |
|
1124 // ----------------------------------------------------------------------------- |
|
1125 // |
|
1126 TInt DIscChannel::IsPending( |
|
1127 const TUint16 aReqNumber ) |
|
1128 { |
|
1129 TInt error( KErrNone ); |
|
1130 if ( iIscRequests[aReqNumber] ) |
|
1131 { |
|
1132 error = KRequestPending; |
|
1133 } |
|
1134 else |
|
1135 { |
|
1136 // error is KErrNone |
|
1137 } |
|
1138 return error; |
|
1139 } |
|
1140 // ----------------------------------------------------------------------------- |
|
1141 // DIscChannel::CompleteRequest |
|
1142 // Function to complete clients pending asynchronous request |
|
1143 // ( other items were commented in a header ). |
|
1144 // ----------------------------------------------------------------------------- |
|
1145 // |
|
1146 void DIscChannel::CompleteRequest( |
|
1147 TInt aOperation, |
|
1148 TInt aCompleteStatus ) |
|
1149 { |
|
1150 C_TRACE( ( _T( "DIscChannel::CompleteRequest(0x%x, 0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aOperation, aCompleteStatus, iChannelNumber, this ) ); |
|
1151 |
|
1152 if ( aOperation < EIscAsyncLast ) |
|
1153 { |
|
1154 |
|
1155 TRequestStatus* requestStatus = iIscRequests[aOperation]; |
|
1156 if ( requestStatus ) |
|
1157 { |
|
1158 // In case of higher priority thread, set request to NULL from the request table before actual completing |
|
1159 iIscRequests[aOperation] = NULL; |
|
1160 Kern::RequestComplete( iThread, requestStatus, aCompleteStatus ); |
|
1161 } |
|
1162 } |
|
1163 else |
|
1164 { |
|
1165 // Do nothing |
|
1166 } |
|
1167 |
|
1168 C_TRACE( ( _T( "DIscChannel::CompleteRequest - return void" ) ) ); |
|
1169 |
|
1170 } |
|
1171 |
|
1172 // ----------------------------------------------------------------------------- |
|
1173 // DIscChannel::InitializeComplete |
|
1174 // Initialization complete dfc |
|
1175 // ( other items were commented in a header ). |
|
1176 // ----------------------------------------------------------------------------- |
|
1177 // |
|
1178 void DIscChannel::InitializeComplete( |
|
1179 TAny* aPtr ) |
|
1180 { |
|
1181 C_TRACE( ( _T( "DIscChannel::InitializeComplete(0x%x)" ), aPtr ) ); |
|
1182 |
|
1183 DIscChannel* ThisPtr = ( DIscChannel* )aPtr; |
|
1184 if ( KErrNone == ThisPtr->iDataTransmissionErrorCode ) |
|
1185 { |
|
1186 ThisPtr->DoMultiplexerInitialize(); |
|
1187 } |
|
1188 else |
|
1189 { |
|
1190 ThisPtr->CompleteRequest( EIscAsyncInitializeModemInterface, ThisPtr->iDataTransmissionErrorCode ); |
|
1191 } |
|
1192 C_TRACE( ( _T( "DIscChannel::InitializeComplete - return 0x%x" ) ) ); |
|
1193 |
|
1194 } |
|
1195 |
|
1196 // ----------------------------------------------------------------------------- |
|
1197 // DIscChannel::DoMultiplexerInitialize |
|
1198 // Completes the multiplexer initialization |
|
1199 // ( other items were commented in a header ). |
|
1200 // ----------------------------------------------------------------------------- |
|
1201 // |
|
1202 void DIscChannel::DoMultiplexerInitialize() |
|
1203 { |
|
1204 C_TRACE( ( _T( "DIscChannel::DoMultiplexerInitialize() channelPtr 0x%x" ), this ) ); |
|
1205 |
|
1206 if ( iIscRequests[EIscAsyncInitializeModemInterface] ) |
|
1207 { |
|
1208 |
|
1209 iIscDevice->iIscMultiplexerInterface->InitializeMultiplexer( |
|
1210 EIscAsyncInitializeModemInterface, |
|
1211 *iMultiplexerIniData, |
|
1212 this ); |
|
1213 } |
|
1214 |
|
1215 C_TRACE( ( _T( "DIscChannel::DoMultiplexerInitialize - return void" ) ) ); |
|
1216 } |
|
1217 |
|
1218 // ----------------------------------------------------------------------------- |
|
1219 // DIscChannel::StoreFrame |
|
1220 // Stores the incoming frame to channels receive queue |
|
1221 // ( other items were commented in a header ). |
|
1222 // ----------------------------------------------------------------------------- |
|
1223 // |
|
1224 void DIscChannel::StoreFrame( TDesC8* aData ) |
|
1225 { |
|
1226 C_TRACE( ( _T( "DIscChannel::StoreFrame(0x%x) channelId 0x%x channelPtr 0x%x" ), aData, iChannelNumber, this ) ); |
|
1227 |
|
1228 TInt error( KErrNone ); |
|
1229 |
|
1230 TIscFrameInfo frameInfo; |
|
1231 iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *aData, frameInfo ); |
|
1232 |
|
1233 if ( frameInfo.frameType == EIscDataFrame ) |
|
1234 { |
|
1235 C_TRACE( ( _T( "DIscChannel::StoreFrame dataFrame" ) ) ); |
|
1236 error = iDataFrameRxQueue->Add( ( TAny* )aData ); |
|
1237 if ( error == KErrNone ) |
|
1238 { |
|
1239 if ( iDataFrameRxQueue->Count() >= iIscChannelHighWaterMark |
|
1240 && iDLFlowControlStatus == EIscFlowControlOff ) |
|
1241 { |
|
1242 iIscDevice->DLFlowControlNotify( EIscFlowControlOn, iChannelNumber, this ); |
|
1243 iDLFlowControlStatus = EIscFlowControlOn; |
|
1244 } |
|
1245 else if ( iDataFrameRxQueue->Count() <= iIscChannelLowWaterMark |
|
1246 && iDLFlowControlStatus != EIscFlowControlOff ) |
|
1247 { |
|
1248 iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this ); |
|
1249 iDLFlowControlStatus = EIscFlowControlOff; |
|
1250 } |
|
1251 else |
|
1252 { |
|
1253 // Do nothing |
|
1254 } |
|
1255 } |
|
1256 else |
|
1257 { |
|
1258 // Set overflow flag on. Complete next DataReceive with KErrOverFlow |
|
1259 TRACE_ASSERT_ALWAYS; |
|
1260 iOverFlow = ETrue; |
|
1261 iIscDevice->ReleaseMemoryBlock( ( TDes8* )aData ); |
|
1262 } |
|
1263 } |
|
1264 |
|
1265 else |
|
1266 { |
|
1267 C_TRACE( ( _T( "DIscChannel::StoreFrame controlFrame" ) ) ); |
|
1268 error = iFrameRxQueue->Add( ( TAny* )aData ); |
|
1269 if ( error != KErrNone ) |
|
1270 { |
|
1271 C_TRACE( ( _T( "DIscChannel::StoreFrame() CONTROL FRAME OVERFLOW channel %d" ), iChannelNumber ) ); |
|
1272 TRACE_ASSERT_ALWAYS; |
|
1273 iClientPanic = ETrue; |
|
1274 iIscDevice->ReleaseMemoryBlock( ( TDes8* )aData ); |
|
1275 } |
|
1276 } |
|
1277 |
|
1278 C_TRACE( ( _T( "DIscChannel::StoreFrame - return void" ) ) ); |
|
1279 } |
|
1280 |
|
1281 // ----------------------------------------------------------------------------- |
|
1282 // DIscChannel::EmptyBuffers |
|
1283 // Goes through channel's queue and delivers possible frame( s ) to client |
|
1284 // ( other items were commented in a header ). |
|
1285 // ----------------------------------------------------------------------------- |
|
1286 // |
|
1287 void DIscChannel::EmptyBuffers() |
|
1288 { |
|
1289 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr 0x%x" ),iChannelNumber, this ) ); |
|
1290 |
|
1291 if ( iDataFrameRxQueue->NextBufferLength() > KErrNone ) |
|
1292 { |
|
1293 TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst(); |
|
1294 TIscFrameInfo frameInfo; |
|
1295 TInt desMaxLen( KErrNone ); |
|
1296 |
|
1297 iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *tempPtr, frameInfo ); |
|
1298 |
|
1299 // frame incoming, and datareceive request active |
|
1300 if ( iIscRequests[EIscAsyncDataReceive] && frameInfo.frameType == EIscDataFrame ) |
|
1301 { |
|
1302 if ( frameInfo.concatenation == EIscNoConcatenation ) |
|
1303 { |
|
1304 desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iDataReceiveBufPtr ); |
|
1305 |
|
1306 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data desMaxLen %d" ),desMaxLen ) ); |
|
1307 |
|
1308 TRACE_ASSERT( desMaxLen > KErrNone ); |
|
1309 |
|
1310 // check that client's memory block is big enough |
|
1311 if ( desMaxLen >= frameInfo.writeLength ) |
|
1312 { |
|
1313 // create a temporary descriptor for writing since we're |
|
1314 // necessary not writing the whole contents of the |
|
1315 // source descriptor, only the part that ISC Multiplexer |
|
1316 // wants |
|
1317 TPtr8 writePtr( ( TUint8* )( tempPtr->Ptr() + frameInfo.writeStartIndex ), |
|
1318 frameInfo.writeLength, |
|
1319 frameInfo.writeLength ); |
|
1320 |
|
1321 TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, 0 ); |
|
1322 |
|
1323 TRACE_ASSERT( r == KErrNone ); |
|
1324 |
|
1325 // remove the pointer from queue and release the memory block |
|
1326 // but only if the ThreadWrite was successfull |
|
1327 if ( r == KErrNone ) |
|
1328 { |
|
1329 iDataFrameRxQueue->DeleteFirst(); |
|
1330 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
1331 if ( iOverFlow ) |
|
1332 { |
|
1333 iOverFlow = EFalse; |
|
1334 CompleteRequest( EIscAsyncDataReceive, KErrOverflow ); |
|
1335 } |
|
1336 else |
|
1337 { |
|
1338 CompleteRequest( EIscAsyncDataReceive, KErrNone ); |
|
1339 } |
|
1340 } |
|
1341 else |
|
1342 { |
|
1343 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data ThreadWrite %d" ), r ) ); |
|
1344 CompleteRequest( EIscAsyncDataReceive, r ); |
|
1345 } |
|
1346 } |
|
1347 // client buffer too small |
|
1348 else |
|
1349 { |
|
1350 TUint16 tempLen( frameInfo.writeLength ); |
|
1351 TPtr8 tempLenDes( ( TUint8* )&tempLen, sizeof ( TUint16 ), sizeof ( TUint16 ) ); |
|
1352 |
|
1353 TInt r = ThreadWrite( ( TAny* )iNeededDataBufLen, &tempLenDes, 0 ); |
|
1354 TRACE_ASSERT( r == KErrNone ); |
|
1355 if ( r != KErrNone ) |
|
1356 { |
|
1357 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data ThreadWrite %d" ), r ) ); |
|
1358 } |
|
1359 |
|
1360 CompleteRequest( EIscAsyncDataReceive, KErrNoMemory ); |
|
1361 } |
|
1362 } |
|
1363 else |
|
1364 { |
|
1365 HandleConcatenatedDataFrame( tempPtr, frameInfo ); |
|
1366 } |
|
1367 } |
|
1368 } |
|
1369 // no frames in data queue |
|
1370 else |
|
1371 { |
|
1372 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr No frames in data queue" ), iChannelNumber, this ) ); |
|
1373 } |
|
1374 |
|
1375 // Check if there is frame in queue |
|
1376 if ( iFrameRxQueue->NextBufferLength() > KErrNone ) |
|
1377 { |
|
1378 TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst(); |
|
1379 TIscFrameInfo frameInfo; |
|
1380 TInt desMaxLen( KErrNone ); |
|
1381 |
|
1382 iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *tempPtr, frameInfo ); |
|
1383 |
|
1384 // frame incoming and normal receive request active |
|
1385 if ( iIscRequests[EIscAsyncReceive] && frameInfo.frameType == EIscNonDataFrame ) |
|
1386 { |
|
1387 if ( frameInfo.concatenation == EIscNoConcatenation ) |
|
1388 { |
|
1389 desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iReceiveBufPtr ); |
|
1390 |
|
1391 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() desMaxLen %d" ),desMaxLen ) ); |
|
1392 |
|
1393 TRACE_ASSERT( desMaxLen > KErrNone ); |
|
1394 |
|
1395 // check that client's memory block is big enough |
|
1396 if ( desMaxLen >= frameInfo.writeLength ) |
|
1397 { |
|
1398 // create a temporary descriptor for writing since we're |
|
1399 // necessary not writing the whole contents of the |
|
1400 // source descriptor, only the part that ISC Multiplexer |
|
1401 // wants |
|
1402 TPtr8 writePtr( ( TUint8* )( tempPtr->Ptr() + frameInfo.writeStartIndex ), |
|
1403 frameInfo.writeLength, |
|
1404 frameInfo.writeLength ); |
|
1405 |
|
1406 TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, 0 ); |
|
1407 |
|
1408 TRACE_ASSERT( r == KErrNone ); |
|
1409 |
|
1410 // remove the pointer from queue and release the memory block |
|
1411 // but only if the ThreadWrite was successfull |
|
1412 if ( r == KErrNone ) |
|
1413 { |
|
1414 iFrameRxQueue->DeleteFirst(); |
|
1415 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
1416 if ( iClientPanic ) |
|
1417 { |
|
1418 iClientPanic = EFalse; |
|
1419 CompleteRequest( EIscAsyncReceive, KErrOverflow ); |
|
1420 } |
|
1421 else |
|
1422 { |
|
1423 CompleteRequest( EIscAsyncReceive, KErrNone ); |
|
1424 } |
|
1425 } |
|
1426 else |
|
1427 { |
|
1428 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() ThreadWrite %d" ), r ) ); |
|
1429 CompleteRequest( EIscAsyncReceive, r ); |
|
1430 } |
|
1431 } |
|
1432 // client buffer too small |
|
1433 else |
|
1434 { |
|
1435 TUint16 tempLen = frameInfo.writeLength; |
|
1436 TPtr8 tempLenDes( ( TUint8* )&tempLen, sizeof ( TUint16 ), sizeof ( TUint16 ) ); |
|
1437 |
|
1438 TInt r = ThreadWrite ( ( TAny* )iNeededBufLen, &tempLenDes, 0 ); |
|
1439 TRACE_ASSERT( r == KErrNone ); |
|
1440 if ( r != KErrNone ) |
|
1441 { |
|
1442 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() ThreadWrite %d" ), r ) ); |
|
1443 } |
|
1444 |
|
1445 CompleteRequest( EIscAsyncReceive, KErrNoMemory ); |
|
1446 } |
|
1447 } |
|
1448 else |
|
1449 { |
|
1450 HandleConcatenatedFrame( tempPtr, frameInfo ); |
|
1451 } |
|
1452 } |
|
1453 } |
|
1454 // no frames in queue |
|
1455 else |
|
1456 { |
|
1457 C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr 0x%x No frames in queue" ), iChannelNumber, this ) ); |
|
1458 } |
|
1459 |
|
1460 // If possible, set flow control off from data frame receiving |
|
1461 if ( iDataFrameRxQueue->Count() <= iIscChannelLowWaterMark |
|
1462 && iDLFlowControlStatus != EIscFlowControlOff ) |
|
1463 { |
|
1464 iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this ); |
|
1465 iDLFlowControlStatus = EIscFlowControlOff; |
|
1466 } |
|
1467 |
|
1468 |
|
1469 C_TRACE( ( _T( "DIscChannel::EmptyBuffers - return void" ) ) ); |
|
1470 |
|
1471 } |
|
1472 |
|
1473 // ----------------------------------------------------------------------------- |
|
1474 // DIscChannel::HandleConcatenatedDataFrame |
|
1475 // Copies several data frames to clients buffer if needed before compliting receive request |
|
1476 // ( other items were commented in a header ). |
|
1477 // ----------------------------------------------------------------------------- |
|
1478 // |
|
1479 void DIscChannel::HandleConcatenatedDataFrame( TDes8* aPtr, TIscFrameInfo& aInfo ) |
|
1480 { |
|
1481 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame(0x%x, 0x%x) channelPtr 0x%x" ), aPtr, &aInfo, this ) ); |
|
1482 TInt desMaxLen( KErrNone ); |
|
1483 TInt desLen( KErrNone ); |
|
1484 TUint16 totalLength( 0 ); |
|
1485 |
|
1486 desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iDataReceiveBufPtr ); |
|
1487 desLen = Kern::ThreadGetDesLength( iThread, iDataReceiveBufPtr ); |
|
1488 |
|
1489 if ( aInfo.totalLength > KErrNone ) |
|
1490 { |
|
1491 totalLength = aInfo.totalLength; |
|
1492 } |
|
1493 else |
|
1494 { |
|
1495 totalLength = desMaxLen; |
|
1496 } |
|
1497 switch ( aInfo.concatenation ) |
|
1498 { |
|
1499 // first frame of a larger data chunk |
|
1500 case EIscConcatenationDataStart: |
|
1501 { |
|
1502 // check whether the whole data amount will fit into the user buffer |
|
1503 if ( desMaxLen >= ( desLen + aInfo.writeLength ) && desMaxLen >= totalLength ) |
|
1504 { |
|
1505 // create a temporary descriptor for writing since we're |
|
1506 // necessary not writing the whole contents of the |
|
1507 // source descriptor, only the part that ISC Multiplexer |
|
1508 // wants |
|
1509 TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ), |
|
1510 aInfo.writeLength, |
|
1511 aInfo.writeLength ); |
|
1512 |
|
1513 // start writing the data at offset 0 since this is the first frame |
|
1514 TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, 0 ); |
|
1515 |
|
1516 // remove the pointer from queue and release the memory block |
|
1517 // but only if the ThreadWrite was successfull |
|
1518 // we do not complete the user request until EIscConcatenationDataEnd |
|
1519 if ( r == KErrNone ) |
|
1520 { |
|
1521 iDataFrameRxQueue->DeleteFirst(); |
|
1522 iIscDevice->ReleaseMemoryBlock( aPtr ); |
|
1523 } |
|
1524 else |
|
1525 { |
|
1526 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() ThreadWrite %d" ), r ) ); |
|
1527 TRACE_ASSERT_ALWAYS; |
|
1528 CompleteRequest( EIscAsyncDataReceive, KErrWrite ); |
|
1529 } |
|
1530 } |
|
1531 else // buffer too small |
|
1532 { |
|
1533 TRACE_ASSERT( totalLength >= ( desLen + aInfo.writeLength ) ); |
|
1534 TPtr8 tempLenDes( ( TUint8* )&totalLength, sizeof ( TUint16 ), sizeof ( TUint16 ) ); |
|
1535 TInt r = ThreadWrite ( ( TAny* )iNeededDataBufLen, &tempLenDes, 0 ); |
|
1536 TRACE_ASSERT( r == KErrNone ); |
|
1537 if ( r != KErrNone ) |
|
1538 { |
|
1539 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() data start KErrNoMemory ThreadWrite %d" ), r ) ); |
|
1540 } |
|
1541 |
|
1542 CompleteRequest( EIscAsyncDataReceive, KErrNoMemory ); |
|
1543 } |
|
1544 break; |
|
1545 } |
|
1546 case EIscConcatenationData: |
|
1547 case EIscConcatenationDataEnd: |
|
1548 { |
|
1549 // check whether the next frame fits to the remaining buffer |
|
1550 if ( ( desMaxLen - desLen ) >= aInfo.writeLength ) |
|
1551 { |
|
1552 // create a temporary descriptor for writing since we're |
|
1553 // necessary not writing the whole contents of the |
|
1554 // source descriptor, only the part that ISC Multiplexer |
|
1555 // wants |
|
1556 TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ), |
|
1557 aInfo.writeLength, |
|
1558 aInfo.writeLength ); |
|
1559 |
|
1560 // start writing the data at offset desLen |
|
1561 TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, desLen ); |
|
1562 TRACE_ASSERT( r == KErrNone ); |
|
1563 // remove the pointer from queue and release the memory block |
|
1564 // but only if the ThreadWrite was successfull |
|
1565 if ( r == KErrNone ) |
|
1566 { |
|
1567 iDataFrameRxQueue->DeleteFirst(); |
|
1568 iIscDevice->ReleaseMemoryBlock( aPtr ); |
|
1569 } |
|
1570 else |
|
1571 { |
|
1572 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() data ThreadWrite %d" ), r ) ); |
|
1573 } |
|
1574 |
|
1575 // complete client request if the frame was the last one |
|
1576 if ( aInfo.concatenation == EIscConcatenationDataEnd ) |
|
1577 { |
|
1578 if ( r == KErrNone ) |
|
1579 { |
|
1580 CompleteRequest( EIscAsyncDataReceive, KErrNone ); |
|
1581 } |
|
1582 else |
|
1583 { |
|
1584 CompleteRequest( EIscAsyncDataReceive, KErrWrite ); |
|
1585 } |
|
1586 } |
|
1587 } |
|
1588 else |
|
1589 { |
|
1590 CompleteRequest( EIscAsyncDataReceive, KErrUnderflow ); |
|
1591 } |
|
1592 break; |
|
1593 } |
|
1594 default: |
|
1595 { |
|
1596 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoCancel ); |
|
1597 break; |
|
1598 } |
|
1599 } |
|
1600 } |
|
1601 |
|
1602 // ----------------------------------------------------------------------------- |
|
1603 // DIscChannel::HandleConcatenatedFrame |
|
1604 // Copies several frames to clients buffer if needed before compliting receive request |
|
1605 // ( other items were commented in a header ). |
|
1606 // ----------------------------------------------------------------------------- |
|
1607 // |
|
1608 void DIscChannel::HandleConcatenatedFrame( TDes8* aPtr, TIscFrameInfo& aInfo ) |
|
1609 { |
|
1610 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame(0x%x, 0x%x) channelPtr 0x%x" ), aPtr, &aInfo, this ) ); |
|
1611 TInt desMaxLen( 0 ); |
|
1612 TInt desLen( 0 ); |
|
1613 TUint16 totalLength( 0 ); |
|
1614 |
|
1615 desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iReceiveBufPtr ); |
|
1616 desLen = Kern::ThreadGetDesLength( iThread, iReceiveBufPtr ); |
|
1617 |
|
1618 if ( aInfo.totalLength > 0 ) |
|
1619 { |
|
1620 totalLength = aInfo.totalLength; |
|
1621 } |
|
1622 else |
|
1623 { |
|
1624 totalLength = desMaxLen; |
|
1625 } |
|
1626 switch ( aInfo.concatenation ) |
|
1627 { |
|
1628 // first frame of a larger data chunk |
|
1629 case EIscConcatenationDataStart: |
|
1630 { |
|
1631 // check whether the whole data amount will fit into the user buffer |
|
1632 if ( desMaxLen >= ( desLen + aInfo.writeLength ) && desMaxLen >= totalLength ) |
|
1633 { |
|
1634 // create a temporary descriptor for writing since we're |
|
1635 // necessary not writing the whole contents of the |
|
1636 // source descriptor, only the part that ISC Multiplexer |
|
1637 // wants |
|
1638 TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ), |
|
1639 aInfo.writeLength, |
|
1640 aInfo.writeLength ); |
|
1641 |
|
1642 // start writing the data at offset 0 since this is the first frame |
|
1643 TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, 0 ); |
|
1644 TRACE_ASSERT( r == KErrNone ); |
|
1645 |
|
1646 // remove the pointer from queue and release the memory block |
|
1647 // but only if the ThreadWrite was successfull |
|
1648 // we do not complete the user request until EIscConcatenationDataEnd |
|
1649 if ( r == KErrNone ) |
|
1650 { |
|
1651 iFrameRxQueue->DeleteFirst(); |
|
1652 iIscDevice->ReleaseMemoryBlock( aPtr ); |
|
1653 } |
|
1654 else |
|
1655 { |
|
1656 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) ); |
|
1657 CompleteRequest( EIscAsyncReceive, KErrWrite ); |
|
1658 } |
|
1659 } |
|
1660 else // buffer too small |
|
1661 { |
|
1662 TRACE_ASSERT( totalLength >= ( desLen + aInfo.writeLength ) ); |
|
1663 TPtr8 tempLenDes( ( TUint8* )&totalLength, sizeof ( TUint16 ), sizeof ( TUint16 ) ); |
|
1664 TInt r = ThreadWrite ( ( TAny* )iNeededBufLen, &tempLenDes, 0 ); |
|
1665 TRACE_ASSERT( r == KErrNone ); |
|
1666 if ( r != KErrNone ) |
|
1667 { |
|
1668 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) ); |
|
1669 } |
|
1670 |
|
1671 CompleteRequest( EIscAsyncReceive, KErrNoMemory ); |
|
1672 } |
|
1673 break; |
|
1674 } |
|
1675 case EIscConcatenationData: |
|
1676 case EIscConcatenationDataEnd: |
|
1677 { |
|
1678 // check whether the next frame fits to the remaining buffer |
|
1679 if ( ( desMaxLen - desLen ) >= aInfo.writeLength ) |
|
1680 { |
|
1681 // create a temporary descriptor for writing since we're |
|
1682 // necessary not writing the whole contents of the |
|
1683 // source descriptor, only the part that ISC Multiplexer |
|
1684 // wants |
|
1685 TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ), |
|
1686 aInfo.writeLength, |
|
1687 aInfo.writeLength ); |
|
1688 |
|
1689 // start writing the data at offset desLen |
|
1690 TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, desLen ); |
|
1691 |
|
1692 if ( r != KErrNone ) |
|
1693 { |
|
1694 C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) ); |
|
1695 } |
|
1696 // remove the pointer from queue and release the memory block |
|
1697 // but only if the ThreadWrite was successfull |
|
1698 if ( r == KErrNone ) |
|
1699 { |
|
1700 iFrameRxQueue->DeleteFirst(); |
|
1701 iIscDevice->ReleaseMemoryBlock( aPtr ); |
|
1702 } |
|
1703 |
|
1704 // complete client request if the frame was the last one |
|
1705 if ( aInfo.concatenation == EIscConcatenationDataEnd ) |
|
1706 { |
|
1707 if ( r == KErrNone ) |
|
1708 { |
|
1709 CompleteRequest( EIscAsyncReceive, KErrNone ); |
|
1710 } |
|
1711 else |
|
1712 { |
|
1713 CompleteRequest( EIscAsyncReceive, KErrWrite ); |
|
1714 } |
|
1715 } |
|
1716 } |
|
1717 else |
|
1718 { |
|
1719 CompleteRequest( EIscAsyncDataReceive, KErrUnderflow ); |
|
1720 } |
|
1721 break; |
|
1722 } |
|
1723 default: |
|
1724 { |
|
1725 ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand ); |
|
1726 break; |
|
1727 } |
|
1728 } |
|
1729 |
|
1730 } |
|
1731 |
|
1732 // ----------------------------------------------------------------------------- |
|
1733 // DIscChannel::CopyFromUserBuffer |
|
1734 // Copy data from user-thread memory space. |
|
1735 // ( other items were commented in a header ). |
|
1736 // ----------------------------------------------------------------------------- |
|
1737 // |
|
1738 TInt DIscChannel::CopyFromUserBuffer( |
|
1739 const TDesC8& aUserBuffer, |
|
1740 TDes8& aKernelBuffer, |
|
1741 const TInt aOffset ) |
|
1742 { |
|
1743 C_TRACE( ( _T( "DIscChannel::CopyFromUserBuffer(0x%x, 0x%x, 0x%x) channelPtr 0x%x" ), &aUserBuffer, &aKernelBuffer, aOffset, this ) ); |
|
1744 return Kern::ThreadDesRead( iThread, ( TAny* )&aUserBuffer, aKernelBuffer, aOffset, KChunkShiftBy0 ); |
|
1745 |
|
1746 } |
|
1747 |
|
1748 // ----------------------------------------------------------------------------- |
|
1749 // DIscChannel::ThreadWrite |
|
1750 // Writes data/frames to clients buffer |
|
1751 // ( other items were commented in a header ). |
|
1752 // ----------------------------------------------------------------------------- |
|
1753 // |
|
1754 TInt DIscChannel::ThreadWrite( |
|
1755 TAny* dest, |
|
1756 const TDesC8* src, |
|
1757 const TInt aOffset ) |
|
1758 { |
|
1759 C_TRACE( ( _T( "DIscChannel::ThreadWrite(0x%x, 0x%x, 0x%x)" ), dest, src, aOffset ) ); |
|
1760 C_TRACE( ( _T( "DIscChannel::ThreadWrite writeLen 0x%x" ), src->Length() ) ); |
|
1761 |
|
1762 return Kern::ThreadDesWrite( iThread, dest, *src, aOffset, iThread ); |
|
1763 |
|
1764 } |
|
1765 |
|
1766 // ----------------------------------------------------------------------------- |
|
1767 // DIscChannel::ResetBuffers |
|
1768 // Resets buffers |
|
1769 // ( other items were commented in a header ). |
|
1770 // ----------------------------------------------------------------------------- |
|
1771 // |
|
1772 void DIscChannel::ResetBuffers() |
|
1773 { |
|
1774 // Delete pending send frames |
|
1775 iIscDevice->CancelSending( iChannelNumber, this ); |
|
1776 |
|
1777 // Empty receive queue |
|
1778 if ( iFrameRxQueue ) |
|
1779 { |
|
1780 while ( !iFrameRxQueue->Empty() ) |
|
1781 { |
|
1782 TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst(); |
|
1783 iFrameRxQueue->DeleteFirst(); |
|
1784 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
1785 } |
|
1786 } |
|
1787 |
|
1788 // Empty data receive queue |
|
1789 if ( iDataFrameRxQueue ) |
|
1790 { |
|
1791 while ( !iDataFrameRxQueue->Empty() ) |
|
1792 { |
|
1793 TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst(); |
|
1794 iDataFrameRxQueue->DeleteFirst(); |
|
1795 iIscDevice->ReleaseMemoryBlock( tempPtr ); |
|
1796 } |
|
1797 } |
|
1798 } |
|
1799 |
|
1800 // End of File |
|