|
1 /* |
|
2 * Copyright (c) 2009 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 the License "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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <kernel.h> // For Kern |
|
21 #include <nk_priv.h> // For __ASSERT_NO_FAST_MUTEX (published to partners) |
|
22 |
|
23 #include <mmuxtrxif.h> // For MMuxTrxIf |
|
24 #include <mtrxmuxif.h> // For MTrxMuxIf, E... faults |
|
25 |
|
26 #include "mmuxlinkif.h" // For internal MMuxLinkIf |
|
27 #include "multiplexer.h" // For DMultiplexer |
|
28 #include "mux.h" // For DMux |
|
29 #include "multiplexertrace.h" // For C_TRACE.. |
|
30 #include "memapi.h" // For MemApi |
|
31 |
|
32 // Faults |
|
33 enum TMuxFaults |
|
34 { |
|
35 EMuxMemAllocFailure = 0x00, |
|
36 EMuxMemAllocFailure2, |
|
37 EMuxNotThreadContext, |
|
38 EMuxNullParam, |
|
39 EMuxNullPtr, |
|
40 EMuxNullPtr2, |
|
41 EMuxInvalidLinkId, |
|
42 }; |
|
43 |
|
44 EXPORT_C MLinkMuxIf* MLinkMuxIf::Register( MMuxLinkIf* aTrx, const TUint8 aTrxId, const TUint8 aLinkId ) |
|
45 { |
|
46 |
|
47 C_TRACE( ( _T( "MLinkMuxIf::Register 0x%x %d %d<>" ), aTrx, aTrxId, aLinkId ) ); |
|
48 __ASSERT_NO_FAST_MUTEX; |
|
49 ASSERT_THREAD_CONTEXT_ALWAYS( ( EMuxNotThreadContext | EDMuxTraceId << KClassIdentifierShift ) ); |
|
50 return DMultiplexer::RegisterLink( aTrx, aTrxId, aLinkId ); |
|
51 |
|
52 } |
|
53 |
|
54 EXPORT_C MTrxMuxIf* MTrxMuxIf::Register( MMuxTrxIf* aTrx, const TUint8 aTrxId ) |
|
55 { |
|
56 |
|
57 C_TRACE( ( _T( "MLinkMuxIf::Register 0x%x %d<>" ), aTrx, aTrxId ) ); |
|
58 __ASSERT_NO_FAST_MUTEX; |
|
59 MUX_ASSERT_FAULT_MACRO( ( aTrx ), MTrxMuxIf::ENullTrxPointer ); |
|
60 MUX_ASSERT_FAULT_MACRO( ( EAmountOfTrxs > aTrxId ), MTrxMuxIf::EInvalidTrxId ); |
|
61 MUX_ASSERT_FAULT_MACRO( ( ISTAPI_ASSERT_KERNEL_THREAD_CONTEXT_ALWAYS ), MTrxMuxIf::ENotKernelThreadContext ); |
|
62 return DMultiplexer::RegisterTrx( aTrx, aTrxId ); |
|
63 |
|
64 } |
|
65 /* |
|
66 * Can be called in different kernel thread contextes. |
|
67 */ |
|
68 DMux::DMux( |
|
69 const TUint8 aTrxId |
|
70 ) |
|
71 { |
|
72 |
|
73 C_TRACE( ( _T( "DMux::DMux this 0x%x id %d>" ), this, iShTrxId ) ); |
|
74 // Synch with fastMutex, not nested no blocking no allocation, and we need perf. |
|
75 iFastMutex = new NFastMutex(); |
|
76 ASSERT_RESET_ALWAYS( iFastMutex, ( EMuxMemAllocFailure | EDMuxTraceId << KClassIdentifierShift ) ); |
|
77 NKern::FMWait( iFastMutex ); |
|
78 iShTrx = NULL; |
|
79 iShTrxId = aTrxId; |
|
80 for( TInt i( 0 ); i < EMuxAmountOfProtocols; i++ ) |
|
81 { |
|
82 iShLinks[ i ] = NULL; |
|
83 } |
|
84 NKern::FMSignal( iFastMutex ); |
|
85 C_TRACE( ( _T( "DMux::DMux this 0x%x id %d<" ), this, iShTrxId ) ); |
|
86 |
|
87 } |
|
88 |
|
89 /* |
|
90 * Deleted by one thread when kernel is shutting down. |
|
91 */ |
|
92 DMux::~DMux( |
|
93 // None |
|
94 ) |
|
95 { |
|
96 |
|
97 C_TRACE( ( _T( "DMux::~DMux this 0x%x id %d>" ), this, iShTrxId ) ); |
|
98 NKern::FMWait( iFastMutex ); |
|
99 iShTrxId = 0x00; |
|
100 iShTrx = NULL; |
|
101 // NULL due no ownership of items |
|
102 for( TInt i( 0 ); i < EMuxAmountOfProtocols; i++ ) |
|
103 { |
|
104 iShLinks[ i ] = NULL; |
|
105 } |
|
106 NKern::FMSignal( iFastMutex ); |
|
107 // No need to check, if not created already reseted. |
|
108 delete iFastMutex; |
|
109 iFastMutex = NULL; |
|
110 C_TRACE( ( _T( "DMux::~DMux this 0x%x id %d<" ), this, iShTrxId ) ); |
|
111 |
|
112 } |
|
113 |
|
114 TUint8 DMux::GetTrxId( |
|
115 // None |
|
116 ) const |
|
117 { |
|
118 |
|
119 C_TRACE( ( _T( "DMux::GetTrxId this 0x%x id %d<>" ), this, iShTrxId ) ); |
|
120 return iShTrxId; |
|
121 |
|
122 } |
|
123 |
|
124 /* |
|
125 * Can be called in different kernel thread contextes. |
|
126 */ |
|
127 void DMux::SetLink( |
|
128 MMuxLinkIf* aLink, |
|
129 const TUint8 aLinkId |
|
130 ) |
|
131 { |
|
132 |
|
133 C_TRACE( ( _T( "DMux::SetLink 0x%x this 0x%x id %d %d>" ), aLink, this, aLinkId, iShTrxId ) ); |
|
134 __ASSERT_NO_FAST_MUTEX; |
|
135 ASSERT_RESET_ALWAYS( ( aLink ), ( EMuxNullParam | EDMuxTraceId << KClassIdentifierShift ) ); |
|
136 ASSERT_RESET_ALWAYS( ( aLinkId < EMuxAmountOfProtocols ), ( EMuxInvalidLinkId | EDMuxTraceId << KClassIdentifierShift ) ); |
|
137 NKern::FMWait( iFastMutex ); |
|
138 iShLinks[ aLinkId ] = aLink; |
|
139 NKern::FMSignal( iFastMutex ); |
|
140 C_TRACE( ( _T( "DMux::SetLink 0x%x 0x%x this 0x%x id %d %d<" ), aLink, this, aLinkId, iShTrxId ) ); |
|
141 |
|
142 } |
|
143 |
|
144 /* |
|
145 * Most likely called in one kernel thread context, but not limited to one. |
|
146 */ |
|
147 void DMux::SetTrx( |
|
148 MMuxTrxIf* aTrx |
|
149 ) |
|
150 { |
|
151 |
|
152 C_TRACE( ( _T( "DMux::SetTrx 0x%x this 0x%x id %d>" ), aTrx, this, iShTrxId ) ); |
|
153 __ASSERT_NO_FAST_MUTEX; |
|
154 MUX_ASSERT_FAULT_MACRO( ( aTrx ), MTrxMuxIf::ENullTrxPointer ); |
|
155 MUX_ASSERT_FAULT_MACRO( ( !iShTrx ), MTrxMuxIf::ENullTrxPointer ); |
|
156 NKern::FMWait( iFastMutex ); |
|
157 // Set transceiver first and then notify it's status. |
|
158 iShTrx = aTrx; |
|
159 NotifyTrxStatusChangeToAllLinks( ETrue ); |
|
160 NKern::FMSignal( iFastMutex ); |
|
161 C_TRACE( ( _T( "DMux::SetTrx 0x%x 0x%x this 0x%x id %d<" ), aTrx, iShTrx, this, iShTrxId ) ); |
|
162 |
|
163 } |
|
164 |
|
165 // From MTrxMuxIf start |
|
166 |
|
167 /* |
|
168 * Can be called in different kernel thread contextes. |
|
169 */ |
|
170 TDes8& DMux::AllocateBlock( |
|
171 const TUint16 aSize |
|
172 ) |
|
173 { |
|
174 |
|
175 C_TRACE( ( _T( "DMux::AllocateBlock this 0x%x id %d size %d<>" ), this, iShTrxId, aSize ) ); |
|
176 __ASSERT_NO_FAST_MUTEX; |
|
177 MUX_ASSERT_FAULT_MACRO( aSize, MTrxMuxIf::EInvalidSize ); |
|
178 MUX_ASSERT_FAULT_MACRO( ( ISTAPI_ASSERT_KERNEL_THREAD_CONTEXT_ALWAYS ), MTrxMuxIf::ENotKernelThreadContext ); |
|
179 return MemApi::AllocBlock( aSize ); |
|
180 |
|
181 } |
|
182 |
|
183 /* |
|
184 * Can be called in different kernel thread contextes. |
|
185 */ |
|
186 void DMux::DeallocateBlock( |
|
187 TDes8& aBlock |
|
188 ) |
|
189 { |
|
190 |
|
191 C_TRACE( ( _T( "DMux::DeallocateBlock this 0x%x id %d block 0x%x>" ), this, iShTrxId, &aBlock ) ); |
|
192 __ASSERT_NO_FAST_MUTEX; |
|
193 MUX_ASSERT_FAULT_MACRO( ( ISTAPI_ASSERT_KERNEL_THREAD_CONTEXT_ALWAYS ), MTrxMuxIf::ENotKernelThreadContext ); |
|
194 MemApi::DeallocBlock( aBlock ); |
|
195 C_TRACE( ( _T( "DMux::DeallocateBlock this 0x%x id %d block 0x%x<" ), this, iShTrxId, &aBlock ) ); |
|
196 |
|
197 } |
|
198 |
|
199 /* |
|
200 * Most likely called in one kernel thread context, but not limited to one. |
|
201 * Message received from transceiver, should be demultiplexed to appropriate link. |
|
202 */ |
|
203 void DMux::Receive( |
|
204 TDes8& aMsg, |
|
205 const TUint32 aMuxPacket |
|
206 ) |
|
207 { |
|
208 |
|
209 C_TRACE( ( _T( "DMux::Receive this 0x%x id %d msg 0x%x aMuxId 0x%x>" ), this, iShTrxId, &aMsg, aMuxPacket ) ); |
|
210 const TUint8 protocolId = static_cast<TUint8>( aMuxPacket >> 24 ); // TODO macro |
|
211 Kern::Printf( "protocolId=0x%x", protocolId );// TODO TBR (ToBeRemoved) |
|
212 __ASSERT_NO_FAST_MUTEX; |
|
213 MUX_ASSERT_FAULT_MACRO( ( protocolId < EMuxAmountOfProtocols ), MTrxMuxIf::EInvalidMuxingHeader ); |
|
214 MUX_ASSERT_FAULT_MACRO( ( ISTAPI_ASSERT_KERNEL_THREAD_CONTEXT_ALWAYS ), MTrxMuxIf::ENotKernelThreadContext ); |
|
215 // TODO ( aMsg.Length() != protocollenght) |
|
216 NKern::FMWait( iFastMutex ); |
|
217 MMuxLinkIf* link = iShLinks[ protocolId ]; |
|
218 NKern::FMSignal( iFastMutex ); |
|
219 ASSERT_RESET_ALWAYS( ( link ), ( EMuxNullPtr | EDMuxTraceId << KClassIdentifierShift ) ); |
|
220 link->Receive( aMsg ); |
|
221 C_TRACE( ( _T( "DMux::Receive this 0x%x id %d msg 0x%x aMuxId 0x%x<" ), this, iShTrxId, &aMsg, aMuxPacket ) ); |
|
222 |
|
223 } |
|
224 |
|
225 /* |
|
226 * Most likely called in one kernel thread context, but not limited to one. |
|
227 */ |
|
228 void DMux::Unregister( |
|
229 // None |
|
230 ) |
|
231 { |
|
232 |
|
233 C_TRACE( ( _T( "DMux::Unregister this 0x%x id %d trx 0x%x>" ), this, iShTrxId, iShTrx ) ); |
|
234 __ASSERT_NO_FAST_MUTEX; |
|
235 MUX_ASSERT_FAULT_MACRO( ( iShTrx ), MTrxMuxIf::ETrxNotRegistered ); |
|
236 MUX_ASSERT_FAULT_MACRO( ( ISTAPI_ASSERT_KERNEL_THREAD_CONTEXT_ALWAYS ), MTrxMuxIf::ENotKernelThreadContext ); |
|
237 NKern::FMWait( iFastMutex ); |
|
238 NotifyTrxStatusChangeToAllLinks( EFalse ); |
|
239 iShTrx = NULL; |
|
240 NKern::FMSignal( iFastMutex ); |
|
241 C_TRACE( ( _T( "DMux::Unregister this 0x%x id %d trx 0x%x<" ), this, iShTrxId, iShTrx ) ); |
|
242 |
|
243 } |
|
244 |
|
245 // From MTrxMuxIf end |
|
246 |
|
247 // From MLinkMuxIf start |
|
248 void DMux::Send( |
|
249 TDes8& aMsg, |
|
250 const TUint8 aLinkId, |
|
251 const TMessageSendPriority aPriority |
|
252 ) |
|
253 { |
|
254 |
|
255 C_TRACE( ( _T( "DMux::Send this 0x%x id %d msg 0x%x aLinkId 0x%x priority %d <>" ), this, iShTrxId, &aMsg, aLinkId, aPriority ) ); |
|
256 TUint32 muxId = static_cast<TUint32>( aMsg.Length() | aLinkId << 24 ); // TODO macro |
|
257 Kern::Printf( "muxId=0x%x", muxId );//TODO TBR |
|
258 ASSERT_RESET_ALWAYS( ( iShTrx ), ( EMuxNullPtr2 | EDMuxTraceId << KClassIdentifierShift ) ); |
|
259 iShTrx->Transmit( aMsg, (MMuxTrxIf::TDataTransmitPriority) aPriority, muxId ); |
|
260 |
|
261 } |
|
262 |
|
263 // From MLinkMuxIf end |
|
264 |
|
265 // Internal start |
|
266 /* |
|
267 * Called with fast mutex held no blocking operations like traces allowed. |
|
268 */ |
|
269 void DMux::NotifyTrxStatusChangeToAllLinks( |
|
270 TBool aPresent |
|
271 ) |
|
272 { |
|
273 |
|
274 // TODO: Change status so that it can not be happen send from up and status change from down simultaneously |
|
275 for( TInt i( 0 ); i < EMuxAmountOfProtocols; i++ ) |
|
276 { |
|
277 MMuxLinkIf* link = iShLinks[ i ]; |
|
278 if( link ) |
|
279 { |
|
280 // Link must enque a DFC after this call. |
|
281 link->EnqueTrxPresenceChangedDfc( aPresent ); |
|
282 } |
|
283 } |
|
284 |
|
285 } |
|
286 // Internal start end |