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 class CCommFrameReaderAo. |
|
15 // * Class CCommFrameReaderAo is used to request a read from the serial port LDD. |
|
16 // * Class CommFrameReaderAo is an active object and is run by the active |
|
17 // * scheduler when the LDD has completed the read request. |
|
18 // |
|
19 |
|
20 // CommFrameReaderAo.cpp |
|
21 |
|
22 /** @file CommFrameReaderAo.cpp |
|
23 * |
|
24 * The file contains the implementation for class CCommFrameReaderAo. |
|
25 * Class CCommFrameReaderAo is used to request a read from the serial port LDD. |
|
26 * Class CommFrameReaderAo is an active object and is run by the active |
|
27 * scheduler when the LDD has completed the read request |
|
28 */ |
|
29 |
|
30 // Need to add code to package together a frame and then send the |
|
31 // complete frame to the Mux object for defragmentation into a client msg. |
|
32 |
|
33 #include "CommFrameReaderAo.h" |
|
34 #include "Portfactory.h" |
|
35 #include "CsyMsgBufBPFrame.h" |
|
36 #include "Mux0710Protocol.h" |
|
37 #include "CsyDebugLogger.h" |
|
38 #include "ChannelMgrCtrl.h" |
|
39 #include "ChannelMgrCmdData.h" |
|
40 |
|
41 CCommFrameReaderAo* CCommFrameReaderAo::NewL(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol) |
|
42 /** |
|
43 * This methods uses two phase construction and the cleanup stack to create |
|
44 * an instance of class CCommFrameReaderAo. |
|
45 * @param aParent - Pointer to parent |
|
46 * @param aMux0710Protocol - Pointer to Mux 27.010 object |
|
47 * @return Pointer to the created instance |
|
48 */ |
|
49 { |
|
50 _LOG_L4C1("CCommFrameReaderAo::NewL"); |
|
51 |
|
52 CCommFrameReaderAo* c = new (ELeave) CCommFrameReaderAo(aParent, aMux0710Protocol); |
|
53 CleanupStack::PushL(c); |
|
54 c->ConstructL(); |
|
55 CleanupStack::Pop(); |
|
56 return c; |
|
57 } |
|
58 |
|
59 CCommFrameReaderAo::~CCommFrameReaderAo() |
|
60 /** |
|
61 * Destructor. Cancel any outstanding request. |
|
62 */ |
|
63 { |
|
64 _LOG_L4C1("CCommFrameReaderAo::~CCommFrameReaderAo"); |
|
65 Cancel(); |
|
66 } |
|
67 |
|
68 CCommFrameReaderAo::CCommFrameReaderAo(CPortFactory* aParent, CMux0710Protocol* aMux0710Protocol) |
|
69 /** |
|
70 * Constructor. Pass priority of active object to base class. |
|
71 * @param aParent - Pointer to parent |
|
72 * @param aMux0710Protocol - Pointer to Mux 27.010 object |
|
73 */ |
|
74 : CCommReadWriteBaseAo(aParent, aMux0710Protocol, KFrameReaderAoPriority), |
|
75 iFrameReaderState(ECsyWaitingForStartFlag) |
|
76 { |
|
77 } |
|
78 |
|
79 void CCommFrameReaderAo::ConstructL() |
|
80 /** |
|
81 * Retrieve a pointer to the LDD comm port. |
|
82 */ |
|
83 { |
|
84 _LOG_L4C1("CCommFrameReaderAo::ConstructL"); |
|
85 SetBuffersL(); |
|
86 } |
|
87 |
|
88 void CCommFrameReaderAo::DoCancel() |
|
89 /** |
|
90 * Cancel an outstanding request. |
|
91 * @param void |
|
92 */ |
|
93 { |
|
94 _LOG_L4C1("CCommFrameReaderAo::DoCancel"); |
|
95 |
|
96 iCommPort->ReadCancel(); |
|
97 } |
|
98 |
|
99 void CCommFrameReaderAo::BasicOption() |
|
100 /** |
|
101 * Basic option frames |
|
102 * Note this has not been tested since DSample/P2 do not use basic option |
|
103 */ |
|
104 { |
|
105 TUint octet; |
|
106 TBool frameData = EFalse; |
|
107 |
|
108 TInt len = iBuf->Length(); |
|
109 TPtr8 ptr = iBuffer->Des(); |
|
110 _LOG_L3C2("Received %d bytes",len); |
|
111 |
|
112 for (TInt loop = 0; loop < len; loop++) |
|
113 { |
|
114 octet = ptr[loop]; |
|
115 |
|
116 if (octet == KCsy0710StartEndFlag) |
|
117 { |
|
118 // Control bit |
|
119 switch(iFrameReaderState) |
|
120 { |
|
121 case ECsyWaitingForStartFlag: |
|
122 { |
|
123 _LOG_L3C2("[0x%02x] Got start flag",octet); |
|
124 iFrameReaderState = ECsyWaitingForFrameStart; |
|
125 |
|
126 if (iFrameBuf == NULL) |
|
127 { |
|
128 // There is data to process - get a new frame |
|
129 iFrameBuf = iMux0710Protocol->GetFreeFrameBuf(); |
|
130 if (iFrameBuf == NULL) |
|
131 { |
|
132 _LOG_L1C1("** No free frame buffer ** - ignoring frame"); |
|
133 break; |
|
134 } |
|
135 } |
|
136 } |
|
137 break; |
|
138 case ECsyWaitingForFrameStart: |
|
139 { |
|
140 // disregard additional flag |
|
141 } |
|
142 break; |
|
143 case ECsyWaitingForFrameData: |
|
144 { |
|
145 iFrameReaderState = ECsyWaitingForStartFlag; |
|
146 |
|
147 // must be the end flag |
|
148 _LOG_L3C2("[0x%02x] End of frame",octet); |
|
149 if (iFrameBuf) |
|
150 { |
|
151 if(iFrameBuf->iMsg.Length()) |
|
152 { |
|
153 // Frame holds something |
|
154 AddToReceivedFramesList(iFrameBuf); |
|
155 iFrameBuf = NULL; |
|
156 } |
|
157 else |
|
158 { |
|
159 _LOG_L1C1("** zero length frame **"); |
|
160 // MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState)); |
|
161 } |
|
162 } |
|
163 else |
|
164 { |
|
165 _LOG_L3C1("** no frame buffer! **"); |
|
166 } |
|
167 } |
|
168 break; |
|
169 default: |
|
170 // MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState)); |
|
171 _LOG_L1C2("** unexpected flag ** [iFrameReaderState=%d]",iFrameReaderState); |
|
172 break; |
|
173 } |
|
174 } |
|
175 else |
|
176 { |
|
177 if (iFrameReaderState == ECsyWaitingForFrameStart) |
|
178 { |
|
179 iFrameReaderState = ECsyWaitingForFrameData; |
|
180 iFrameBuf->iMsg.Append(octet); |
|
181 |
|
182 #ifdef _DEBUG |
|
183 // This variable should only be set if it debug |
|
184 // Otherwise we get warnings when compiling with ARM v5 |
|
185 TUint dlcNum = octet >> 2; |
|
186 #endif |
|
187 |
|
188 _LOG_L3C3E("[0x%02x] dlcNum=%d", octet, dlcNum); |
|
189 } |
|
190 else |
|
191 { |
|
192 _LOG_L3C2("[0x%02x]",octet); |
|
193 frameData = ETrue; |
|
194 } |
|
195 } |
|
196 |
|
197 if (frameData) |
|
198 { |
|
199 // MAF __ASSERT_DEBUG((iFrameReaderState == ECsyWaitingForFrameData),PANIC(KPanicIllegalState)); |
|
200 |
|
201 TUint frameLen = (TUint) (iFrameBuf->iMsg.Length() + 1); |
|
202 if (frameLen > KMaxAdvFrameSize) |
|
203 { |
|
204 _LOG_L1C3("** length %d will exceed max length %d **", |
|
205 frameLen,KMaxFrameSize); |
|
206 iFrameBuf->iMsg.Zero(); |
|
207 iFrameReaderState = ECsyWaitingForStartFlag; |
|
208 break; |
|
209 } |
|
210 |
|
211 frameData = EFalse; |
|
212 iFrameBuf->iMsg.Append(octet); |
|
213 } |
|
214 } |
|
215 } |
|
216 |
|
217 void CCommFrameReaderAo::AdvancedOption() |
|
218 /** |
|
219 * Advanced option frames |
|
220 */ |
|
221 { |
|
222 TUint octet = 0; |
|
223 TBool frameData = EFalse; |
|
224 |
|
225 TInt len = iBuf->Length(); |
|
226 TPtr8 ptr = iBuffer->Des(); |
|
227 _LOG_L3C2("Received %d bytes",len); |
|
228 |
|
229 TInt startVal = 0; |
|
230 |
|
231 // Check processing (helps when we have lost sync with data due to read error) |
|
232 if ((iFrameReaderState == ECsyWaitingForStartFlag)&&(len)) |
|
233 { |
|
234 // We are on the hunt for the start flag |
|
235 if (iESCRecved) |
|
236 { |
|
237 _LOG_L2C1("Escape flag set - ignore first octet"); |
|
238 iESCRecved = EFalse; |
|
239 } |
|
240 else |
|
241 octet = ptr[0]; |
|
242 |
|
243 if (octet != KCsy0710StartEndFlag) |
|
244 { |
|
245 _LOG_L3C2("[0x%02x]",octet); |
|
246 _LOG_L2C1("* Looking for the start flag *"); |
|
247 do |
|
248 { |
|
249 startVal++; |
|
250 if (startVal == len) |
|
251 break; |
|
252 |
|
253 octet = ptr[startVal]; |
|
254 |
|
255 if (iESCRecved) |
|
256 { |
|
257 iESCRecved = EFalse; |
|
258 continue; |
|
259 } |
|
260 |
|
261 if (octet == KCsy0710EscapeByte) |
|
262 iESCRecved = ETrue; |
|
263 } |
|
264 while (octet != KCsy0710StartEndFlag); |
|
265 |
|
266 _LOG_L2C2("Disregarded %d bytes",startVal); |
|
267 } |
|
268 } |
|
269 |
|
270 // Do processing of the received buffer |
|
271 for (TInt loop = startVal; loop < len; loop++) |
|
272 { |
|
273 octet = ptr[loop]; |
|
274 |
|
275 if (iESCRecved) |
|
276 { |
|
277 _LOG_L3C2("[0x%02x] - Recv ESC before, change this char",octet); |
|
278 octet = (TUint8) (octet^(1<<5)); |
|
279 _LOG_L3C2("Changed to [0x%02x]",octet); |
|
280 iESCRecved = EFalse; |
|
281 frameData = ETrue; |
|
282 } |
|
283 else |
|
284 { |
|
285 if (octet == KCsy0710EscapeByte) |
|
286 { |
|
287 _LOG_L3C1("KCsy0710EscapeByte"); |
|
288 iESCRecved = ETrue; |
|
289 } |
|
290 else if (octet == KCsy0710StartEndFlag) |
|
291 { |
|
292 // Control bit |
|
293 switch(iFrameReaderState) |
|
294 { |
|
295 case ECsyWaitingForFrameData: |
|
296 { |
|
297 iFrameReaderState = ECsyWaitingForStartFlag; |
|
298 |
|
299 if (iFrameBuf) |
|
300 { |
|
301 TInt frameLen = iFrameBuf->iMsg.Length(); |
|
302 if(frameLen > KAdvOptionHeaderSize) |
|
303 { |
|
304 TUint8 checkSum = iFrameBuf->iMsg[frameLen-1]; |
|
305 if (CheckFCS(iFrameBuf->iMsg,KAdvOptionHeaderSize,checkSum)) |
|
306 { |
|
307 // must be the end flag |
|
308 _LOG_L3C2("[0x%02x] End of frame",octet); |
|
309 // Frame holds something |
|
310 AddToReceivedFramesList(iFrameBuf); |
|
311 iFrameBuf = NULL; |
|
312 } |
|
313 else |
|
314 { |
|
315 _LOG_L1C1("** checksum is incorrect - rejecting frame **"); |
|
316 iFrameBuf->iMsg.Zero(); |
|
317 } |
|
318 } |
|
319 else |
|
320 { |
|
321 _LOG_L1C2("** Rejected incorrect length frame %d **",frameLen); |
|
322 iFrameBuf->iMsg.Zero(); |
|
323 } |
|
324 } |
|
325 else |
|
326 { |
|
327 _LOG_L3C1("** no frame buffer! **"); |
|
328 } |
|
329 |
|
330 TInt check = loop+1; |
|
331 if (check == len) |
|
332 break; |
|
333 |
|
334 // There are more bytes in this buffer to process |
|
335 octet = ptr[check]; |
|
336 if (octet != KCsy0710StartEndFlag) |
|
337 { |
|
338 // Frames are back to back |
|
339 _LOG_L2C1("* No start flag - assuming frames back to back *"); |
|
340 octet = KCsy0710StartEndFlag; |
|
341 } |
|
342 } |
|
343 // deliberate fall through |
|
344 case ECsyWaitingForStartFlag: |
|
345 { |
|
346 _LOG_L3C2("[0x%02x] Got start flag",octet); |
|
347 iFrameReaderState = ECsyWaitingForFrameStart; |
|
348 |
|
349 if (iFrameBuf == NULL) |
|
350 { |
|
351 // There is data to process - get a new frame |
|
352 iFrameBuf = iMux0710Protocol->GetFreeFrameBuf(); |
|
353 if (iFrameBuf == NULL) |
|
354 { |
|
355 _LOG_L1C1("** No free frame buffer ** - ignoring frame"); |
|
356 // Note: GetFreeFrameBuf handles the flow control |
|
357 break; |
|
358 } |
|
359 } |
|
360 } |
|
361 break; |
|
362 case ECsyWaitingForFrameStart: |
|
363 { |
|
364 // disregard additional flag |
|
365 } |
|
366 break; |
|
367 default: |
|
368 _LOG_L1C2("** unexpected flag ** [iFrameReaderState=%d]",iFrameReaderState); |
|
369 // MAF __ASSERT_DEBUG(EFalse, PANIC(KPanicIllegalState)); |
|
370 break; |
|
371 } |
|
372 } |
|
373 else |
|
374 { |
|
375 if (iFrameReaderState == ECsyWaitingForFrameStart) |
|
376 iFrameReaderState = ECsyWaitingForFrameData; |
|
377 |
|
378 _LOG_L3C2("[0x%02x]",octet); |
|
379 frameData = ETrue; |
|
380 } |
|
381 } |
|
382 |
|
383 if (frameData) |
|
384 { |
|
385 frameData = EFalse; |
|
386 |
|
387 // MAF __ASSERT_DEBUG((iFrameReaderState == ECsyWaitingForFrameData),PANIC(KPanicIllegalState)); |
|
388 |
|
389 if (iFrameBuf) |
|
390 { |
|
391 TUint frameLen = (TUint) (iFrameBuf->iMsg.Length() + 1); |
|
392 if (frameLen > KMaxAdvFrameSize) |
|
393 { |
|
394 _LOG_L1C2("** length will exceed max length %d **", |
|
395 KMaxFrameSize); |
|
396 iFrameBuf->iMsg.Zero(); |
|
397 iFrameReaderState = ECsyWaitingForStartFlag; |
|
398 break; |
|
399 } |
|
400 |
|
401 iFrameBuf->iMsg.Append(octet); |
|
402 } |
|
403 else |
|
404 { |
|
405 // it should not be possible to enter this condition |
|
406 |
|
407 _LOG_L1C2("** No frame buffer allocated for frame ** [iFrameReaderState=%d]",iFrameReaderState); |
|
408 // MAF __ASSERT_DEBUG(EFalse,PANIC(KPanicIllegalState)); |
|
409 } |
|
410 } |
|
411 } |
|
412 } |
|
413 |
|
414 void CCommFrameReaderAo::NonMuxed() |
|
415 { |
|
416 if (iMux0710Protocol->ParseATResponse(*iBuf) == KErrNone) |
|
417 { |
|
418 iFrameReaderState = ECsyWaitingForStartFlag; |
|
419 _LOG_L3C1("ParseATResponse returned KErrNone"); |
|
420 } |
|
421 } |
|
422 |
|
423 void CCommFrameReaderAo::RunL() |
|
424 /** |
|
425 * This method is invoked by the active scheduler when the read request |
|
426 * to the LDD has completed. |
|
427 */ |
|
428 { |
|
429 if (iStatus.Int()) |
|
430 { |
|
431 _LOG_L3C1(" "); // please leave separator in |
|
432 _LOG_L1C2("** CCommFrameReaderAo::RunL [iStatus %d] **",iStatus.Int()); |
|
433 |
|
434 // assumption here, whatever the error we will be able to repost |
|
435 // another request to readoneormore from the serial device driver. |
|
436 |
|
437 if (iFrameBuf) |
|
438 { |
|
439 iMux0710Protocol->AddFrameFreeQ(iFrameBuf); |
|
440 iFrameBuf = NULL; |
|
441 } |
|
442 |
|
443 //reset state |
|
444 iESCRecved = EFalse; |
|
445 iFrameReaderState = ECsyWaitingForStartFlag; |
|
446 |
|
447 iStatus = KRequestPending; |
|
448 SetActive(); |
|
449 iCommPort->ReadOneOrMore(iStatus, *iBuf); |
|
450 return; |
|
451 } |
|
452 |
|
453 if (iFrameBuf == NULL) |
|
454 { |
|
455 // Only show this log if start of a new frame |
|
456 _LOG_L3C1(" "); // please leave separator in |
|
457 _LOG_L3C1("CCommFrameReaderAo::RunL - start of read"); |
|
458 } |
|
459 |
|
460 if (!iMux0710Protocol->IsMuxModeEnabled()) |
|
461 { |
|
462 NonMuxed(); |
|
463 } |
|
464 else |
|
465 { |
|
466 // mux mode is enabled |
|
467 // process recv data according to our current state |
|
468 |
|
469 #ifndef _27010ADVANCEOPTION |
|
470 |
|
471 BasicOption(); |
|
472 |
|
473 #else |
|
474 AdvancedOption(); |
|
475 |
|
476 #endif |
|
477 } |
|
478 |
|
479 if (!IsActive()) |
|
480 { |
|
481 iStatus = KRequestPending; |
|
482 SetActive(); |
|
483 iCommPort->ReadOneOrMore(iStatus, *iBuf); |
|
484 } |
|
485 } |
|
486 |
|
487 void CCommFrameReaderAo::Read() |
|
488 /** |
|
489 * This method is called to start the process to read an ascii string |
|
490 * (e.g. response to initial AT+CMUX=0,0,5 command) or a frame from |
|
491 * the serial port LDD. |
|
492 * Note that this method will only be called once and then the RunL |
|
493 * will handle the reading of the comm port. |
|
494 */ |
|
495 { |
|
496 _LOG_L4C1(">>CCommFrameReaderAo::Read"); |
|
497 |
|
498 if (!IsActive()) |
|
499 { |
|
500 _LOG_L3C1("Read not active"); |
|
501 |
|
502 // Set the object active |
|
503 iStatus = KRequestPending; |
|
504 SetActive(); |
|
505 iCommPort->ReadOneOrMore(iStatus, *iBuf); |
|
506 } |
|
507 else |
|
508 { |
|
509 _LOG_L2C1("** Already active **"); |
|
510 } |
|
511 |
|
512 _LOG_L4C1("<<CCommFrameReaderAo::Read"); |
|
513 } |
|
514 |
|
515 void CCommFrameReaderAo::ReadCancel() |
|
516 /** |
|
517 * Cancel a read request. |
|
518 */ |
|
519 { |
|
520 _LOG_L4C1(">>CCommFrameReaderAo::ReadCancel"); |
|
521 |
|
522 iCommPort->ReadCancel(); |
|
523 if (iFrameBuf) |
|
524 { |
|
525 // return buffer to free frame queue |
|
526 iMux0710Protocol->AddFrameFreeQ(iFrameBuf); |
|
527 iFrameBuf = NULL; |
|
528 } |
|
529 |
|
530 _LOG_L4C1("<<CCommFrameReaderAo::ReadCancel"); |
|
531 } |
|
532 |
|
533 TBool CCommFrameReaderAo::CheckFCS(TDes8& aBuffer, TInt aLen, TUint8 aSuppliedChecksum) |
|
534 /** |
|
535 * This method checks the checksum for the specified buffer with the |
|
536 * specified length. |
|
537 * |
|
538 * @param aBuffer - Data |
|
539 * @param aLen - Number of bytes in the Buffer for which CheckSum to be calculated |
|
540 * @return ETrue if checksum is okay |
|
541 */ |
|
542 { |
|
543 TUint8 frameCheckSum = 0xFF; |
|
544 |
|
545 for (TInt i=0; i < aLen; i++) |
|
546 { |
|
547 frameCheckSum = crctable[(frameCheckSum ^ aBuffer[i])]; |
|
548 } |
|
549 |
|
550 // One's Complement |
|
551 frameCheckSum = crctable[(frameCheckSum ^ aSuppliedChecksum)]; |
|
552 |
|
553 if (frameCheckSum == 0xCF) |
|
554 return ETrue; |
|
555 |
|
556 return EFalse; |
|
557 } |
|
558 |
|
559 void CCommFrameReaderAo::AddToReceivedFramesList(CCsyMsgBufBpFrame* aBpFrame) |
|
560 /** |
|
561 * This method is called by the comm frame reader to add the specified |
|
562 * received frame to a c32 port interface queue. The specific C32 port |
|
563 * interface object is determined from the DLC number embedded in the frame. |
|
564 * |
|
565 * @param aBpFrame - Pointer to the received frame |
|
566 */ |
|
567 { |
|
568 _LOG_L4C1(">>CCommFrameReaderAo::AddToReceivedFramesList"); |
|
569 |
|
570 TUint8 dlcNum = aBpFrame->GetDlcNum(); |
|
571 |
|
572 _LOG_L4C2("dlcNum=%d", dlcNum); |
|
573 _LOG_L4C2("frameType=0x%x", aBpFrame->GetFrameType()); |
|
574 |
|
575 // check for a message for the control channel |
|
576 if (dlcNum == 0) |
|
577 { |
|
578 iParent->GetControlChannel()->ProcessRecvFrame(aBpFrame); |
|
579 } |
|
580 else |
|
581 { |
|
582 CChannelMgrCmdData* channel = iParent->FindChannelMgrByDlcNum(dlcNum); |
|
583 if (channel != NULL) |
|
584 channel->ProcessRecvFrame(aBpFrame); |
|
585 else |
|
586 { |
|
587 _LOG_L1C2("** No port defined for dlcNum=%d **", dlcNum); |
|
588 iMux0710Protocol->AddFrameFreeQ(aBpFrame); |
|
589 } |
|
590 } |
|
591 |
|
592 _LOG_L4C1("<<CCommFrameReaderAo::AddToReceivedFramesList"); |
|
593 } |
|
594 |
|