1 // |
|
2 // * Copyright 2004 Neusoft America Inc. |
|
3 // * 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 // * Contributors: |
|
10 // * Keith Collins (Neusoft America Inc.) original software development and additional code and modifications. |
|
11 // * Thomas Gahagen (Neusoft America Inc.) additional code and modifications. |
|
12 // * Zhen Yuan (Neusoft America Inc.) additional code and modifications. |
|
13 // * |
|
14 // * Description: This file contains the implementation for the CPortC32Interface class. |
|
15 // * This class contains methods which are invoked by C32 when the |
|
16 // * associated client RComm public API is invoked. These methods |
|
17 // * are used to create, configure, read, write, and close logical |
|
18 // * serial ports. Instances of this class are created by the CSY's |
|
19 // * Port Factory. |
|
20 // |
|
21 |
|
22 // PortC32Interface.cpp |
|
23 |
|
24 /** @file PortC32Interface.cpp |
|
25 * |
|
26 */ |
|
27 |
|
28 #include <cdbcols.h> |
|
29 #include "PortC32Interface.h" |
|
30 #include "Portfactory.h" |
|
31 #include "Mux0710Protocol.h" |
|
32 #include "CsyMsgBufBPFrame.h" |
|
33 #include "ChannelMgrCmdData.h" |
|
34 #include "CommFrameReaderAo.h" |
|
35 #include "CsyDebugLogger.h" |
|
36 #include "CsyGlobals.h" |
|
37 #include "CommFrameWriterAo.h" |
|
38 |
|
39 CPortC32Interface* CPortC32Interface::NewL(CPortFactory& aPortFactory, |
|
40 CPortFactory::TC32PortInfo& aPortInfo) |
|
41 /** |
|
42 * This method uses two phase construction and the cleanup stack to create |
|
43 * an instance of class CPortC32Interface. |
|
44 * |
|
45 * @param aPortFactory - Reference to the port factory |
|
46 * @param aPortInfo - Reference to the port information |
|
47 * @return Pointer to the created instance |
|
48 */ |
|
49 { |
|
50 _LOG_L4C1( "CPortC32Interface::NewL"); |
|
51 |
|
52 CPortC32Interface* self = new(ELeave) CPortC32Interface(aPortFactory, aPortInfo); |
|
53 TCleanupItem closeSelf(CPortFactory::CloseObject, self); |
|
54 CleanupStack::PushL(closeSelf); |
|
55 self->ConstructL(); |
|
56 CleanupStack::Pop(self); |
|
57 |
|
58 return self; |
|
59 } |
|
60 |
|
61 CPortC32Interface::~CPortC32Interface() |
|
62 /** |
|
63 * Destructor. |
|
64 */ |
|
65 { |
|
66 _LOG_L4C1( ">>CPortC32Interface::~CPortC32Interface"); |
|
67 |
|
68 // let port factory know we are deleted |
|
69 iPortFactory.RemoveC32Port(this); |
|
70 CompleteOutstandingRequest(); |
|
71 |
|
72 iMuxChannel->Close(this); |
|
73 |
|
74 if (iReadBuf) |
|
75 { |
|
76 _LOG_L3C1("Delete read buffer"); |
|
77 delete iReadBuf; |
|
78 } |
|
79 |
|
80 _LOG_L4C1( "<<CPortC32Interface::~CPortC32Interface"); |
|
81 } |
|
82 |
|
83 CPortC32Interface::CPortC32Interface(CPortFactory& aPortFactory, |
|
84 CPortFactory::TC32PortInfo& aPortInfo) |
|
85 /** |
|
86 * Constructor. |
|
87 * |
|
88 * @param aPortFactory - Reference to the port factory |
|
89 * @param aPortInfo - Reference to the port information |
|
90 */ |
|
91 : CPortC32InterfaceBase(aPortFactory, aPortInfo) |
|
92 {} |
|
93 |
|
94 void CPortC32Interface::ConstructL(void) |
|
95 /** |
|
96 * Safe constructor |
|
97 */ |
|
98 { |
|
99 _LOG_L4C1( "CPortC32Interface::ConstructL"); |
|
100 CPortC32InterfaceBase::ConstructL(); |
|
101 } |
|
102 |
|
103 /********************************************************************************/ |
|
104 /* Start of utility methods for CPortC32InterfaceBase */ |
|
105 /********************************************************************************/ |
|
106 |
|
107 TInt CPortC32Interface::QueryReceiveBuffer(TInt& aLength) const |
|
108 /** |
|
109 * Called by C32 when the client queries the size of the receive buffer, |
|
110 * which returns the number of receive characters available to be read by |
|
111 * the C32 client RComm instance. |
|
112 * |
|
113 * @param aLength - Reference to client's buffer length variable |
|
114 * @return KErrNone |
|
115 */ |
|
116 { |
|
117 _LOG_L4C2( "CPortC32Interface::QueryReceiveBuffer [port=%d]", GetPortNumber()); |
|
118 |
|
119 aLength = 0; |
|
120 if (iReadBuf) |
|
121 { |
|
122 aLength = iReadBuf->iMsg.Length(); |
|
123 _LOG_L4C2("iReadBuf aLength=%d", aLength); |
|
124 } |
|
125 else if (!iFramesWaitingToBeReadList.IsEmpty()) |
|
126 { |
|
127 CCsyMsgBufBpFrame* frame = iFramesWaitingToBeReadList.First(); |
|
128 if ((frame)&&(frame->iMsg.Length() >= (KAdvOptionHeaderSize + KChecksumSize))) |
|
129 { |
|
130 #ifdef _27010ADVANCEOPTION |
|
131 aLength = frame->iMsg.Length() - (KAdvOptionHeaderSize + KChecksumSize); |
|
132 #else |
|
133 aLength = frame->iMsg.Length() - (KBasicOptionHeaderSize + KChecksumSize); |
|
134 #endif |
|
135 _LOG_L4C2("iFramesWaitingToBeReadList aLength=%d", aLength); |
|
136 } |
|
137 } |
|
138 |
|
139 return KErrNone; |
|
140 } |
|
141 |
|
142 void CPortC32Interface::ResetBuffers(TUint aFlags) |
|
143 /** |
|
144 * Called by C32 when the client requests to reset the buffers, |
|
145 * by removing all receive and/or transmit messages according to |
|
146 * the specified flags. |
|
147 * |
|
148 * @param aFlags Indicate which buffers (receive and/or transmit) should be reset |
|
149 */ |
|
150 { |
|
151 _LOG_L4C2(">>CPortC32Interface::ResetBuffers [aFlags=%d]", aFlags); |
|
152 _LOG_L4C2("[port=%d]", GetPortNumber()); |
|
153 |
|
154 if (aFlags & KCommResetRx) |
|
155 { |
|
156 _LOG_L4C1("Removing all messages intended for the C32 client"); |
|
157 |
|
158 RemoveWaitingAllFrames(); |
|
159 } |
|
160 |
|
161 if (aFlags & KCommResetTx) |
|
162 { |
|
163 _LOG_L4C1("Removing all messages intended for the modem"); |
|
164 |
|
165 GetMuxChannel()->WriteCancel(); |
|
166 } |
|
167 |
|
168 _LOG_L4C1("<<CPortC32Interface::ResetBuffers"); |
|
169 } |
|
170 |
|
171 void CPortC32Interface::SendFrameToClient(CCsyMsgBufBpFrame* aFrame) |
|
172 /** |
|
173 * This method is called by a CSY Channel object when it has a single |
|
174 * frame to send to a C32 client RComm object. |
|
175 * |
|
176 * @param aFrame - Pointer to message to send to client |
|
177 */ |
|
178 { |
|
179 _LOG_L4C2( "CPortC32Interface::SendFrameToClient [port=%d]", GetPortNumber()); |
|
180 |
|
181 if (aFrame) |
|
182 { |
|
183 // check if queue is empty |
|
184 TBool trigger = iFramesWaitingToBeReadList.IsEmpty(); |
|
185 |
|
186 iFramesWaitingToBeReadList.AddLast(*aFrame); |
|
187 if (trigger) |
|
188 { |
|
189 _LOG_L4C1("No packets already waiting"); |
|
190 if (iIsReadInProgress) |
|
191 { |
|
192 _LOG_L4C1("A read is outstanding"); |
|
193 ReadFromBufOrQueue(); |
|
194 } |
|
195 } |
|
196 |
|
197 // inform client new data is available |
|
198 SetDataAvailable(); |
|
199 } |
|
200 else |
|
201 { |
|
202 //MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState)); |
|
203 } |
|
204 } |
|
205 |
|
206 TBool CPortC32Interface::ReadFromBufOrQueue() |
|
207 /** |
|
208 * This method is called to read from buffer or the frame list |
|
209 * It will read as much as possible. |
|
210 * |
|
211 * @return ETrue if complete the read request |
|
212 */ |
|
213 { |
|
214 _LOG_L4C2( ">>CPortC32Interface::ReadFromBufOrQueue [port=%d]",GetPortNumber()); |
|
215 |
|
216 TBool completedTheReadRequest = EFalse; |
|
217 |
|
218 TInt err = KErrGeneral; |
|
219 TBool cont; |
|
220 do |
|
221 { |
|
222 cont = EFalse; |
|
223 if(iReadBuf==NULL) |
|
224 { |
|
225 //Read data from the frame list |
|
226 if (!iFramesWaitingToBeReadList.IsEmpty()) |
|
227 { |
|
228 _LOG_L4C1("Set to first item"); |
|
229 iReadBuf = iFramesWaitingToBeReadList.First(); |
|
230 if (iReadBuf) |
|
231 { |
|
232 _LOG_L4C1("iReadBuf not null"); |
|
233 // remove msg buf from client list |
|
234 iFramesWaitingToBeReadList.Remove(*iReadBuf); |
|
235 |
|
236 // subtract checksum field |
|
237 TInt frameLength = iReadBuf->iMsg.Length(); |
|
238 _LOG_L4C2("New read buffer frameLength=%d",frameLength); |
|
239 |
|
240 if (frameLength >= KBasicOptionHeaderSize) |
|
241 { |
|
242 iReadBuf->iMsg.SetLength(frameLength - KChecksumSize); |
|
243 |
|
244 // remove leading header ints from frame |
|
245 #ifdef _27010ADVANCEOPTION |
|
246 iReadBuf->iMsg.Delete(0, KAdvOptionHeaderSize); |
|
247 #else |
|
248 iReadBuf->iMsg.Delete(0, KBasicOptionHeaderSize); |
|
249 #endif |
|
250 } |
|
251 else |
|
252 { |
|
253 _LOG_L4C1("Incorrect frame size - freeing read buffer"); |
|
254 iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(iReadBuf); |
|
255 iReadBuf = NULL; |
|
256 } |
|
257 } |
|
258 } |
|
259 } |
|
260 if (iReadBuf) |
|
261 { |
|
262 TInt length = -1; |
|
263 if (iClientLength - iPos < iReadBuf->iMsg.Length()) |
|
264 { |
|
265 length = iClientLength - iPos; |
|
266 _LOG_L4C2("length = %d",length); |
|
267 } |
|
268 |
|
269 if (iConfig.iTerminatorCount > 0) |
|
270 { |
|
271 _LOG_L4C2("iTerminatorCount = %d",iConfig.iTerminatorCount); |
|
272 |
|
273 // First find terminator |
|
274 TInt terminatorLoc = -1; |
|
275 TInt loc; |
|
276 for (TInt i=0; i< iConfig.iTerminatorCount;i++) |
|
277 { |
|
278 loc = iReadBuf->iMsg.LocateF(iConfig.iTerminator[i]); |
|
279 if (loc > KErrNotFound) |
|
280 { |
|
281 if (terminatorLoc == KErrNotFound) |
|
282 { |
|
283 terminatorLoc = loc; |
|
284 } |
|
285 else |
|
286 { |
|
287 terminatorLoc = Min(loc,terminatorLoc); |
|
288 } |
|
289 } |
|
290 } |
|
291 if (terminatorLoc>KErrNotFound) |
|
292 { |
|
293 if (length > KErrNotFound) |
|
294 length = Min(terminatorLoc + 1,length); |
|
295 else |
|
296 length = terminatorLoc + 1; |
|
297 } |
|
298 _LOG_L4C2("length = %d",length); |
|
299 } |
|
300 |
|
301 _LOG_L4C2("Read buf length %d",iReadBuf->iMsg.Length()); |
|
302 |
|
303 if ((iReadBuf->iMsg.Length() >= length) && (length > -1)) |
|
304 { |
|
305 _LOG_L2C2("complete partial read: # %d ", length); |
|
306 |
|
307 iPartialReadBuf.Copy(&iReadBuf->iMsg[0], length); |
|
308 iReadBuf->iMsg.Delete(0, length); |
|
309 |
|
310 err = IPCWrite(iClientBuffer, iPartialReadBuf, iPos); |
|
311 if (err) |
|
312 { |
|
313 _LOG_L1C2("** IPCWrite Error %d **",err); |
|
314 } |
|
315 |
|
316 CompleteReadRequest(err); |
|
317 err = KErrGeneral; |
|
318 |
|
319 completedTheReadRequest = ETrue; |
|
320 iPos = 0; |
|
321 |
|
322 if (iReadBuf->iMsg.Length()==0) |
|
323 { |
|
324 _LOG_L4C1("All data used - freeing read buffer"); |
|
325 iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(iReadBuf); |
|
326 iReadBuf = NULL; |
|
327 } |
|
328 } |
|
329 else |
|
330 { |
|
331 err = IPCWrite(iClientBuffer, iReadBuf->iMsg, iPos); |
|
332 if (err) |
|
333 { |
|
334 _LOG_L1C2("** IPCWrite Error %d **",err); |
|
335 } |
|
336 |
|
337 _LOG_L4C3( "Read: iPos = %d, add %d bytes", iPos, iReadBuf->iMsg.Length()); |
|
338 |
|
339 //try read next frame in the list |
|
340 cont = ETrue; |
|
341 iPos += iReadBuf->iMsg.Length(); |
|
342 |
|
343 _LOG_L4C1("Freeing read buffer"); |
|
344 iPortFactory.GetMux0710Protocol()->AddFrameFreeQ(iReadBuf); |
|
345 iReadBuf = NULL; |
|
346 } |
|
347 } |
|
348 } |
|
349 while (cont); |
|
350 |
|
351 if (iPos>0) |
|
352 { |
|
353 if (iOneOrMore) |
|
354 { |
|
355 CompleteReadRequest(err); |
|
356 iPos = 0; |
|
357 completedTheReadRequest = ETrue; |
|
358 } |
|
359 else |
|
360 { |
|
361 //normal read and have not filled the buffer yet |
|
362 _LOG_L4C3( "Not filled buffer yet iPos = %d, iClientLength = %d", iPos, iClientLength); |
|
363 } |
|
364 } |
|
365 |
|
366 _LOG_L4C2( "<<CPortC32Interface::ReadFromBufOrQueue [completedTheReadRequest=%d]",completedTheReadRequest); |
|
367 return completedTheReadRequest; |
|
368 } |
|