|
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 "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 #include <e32debug.h> |
|
20 #include <e32base.h> |
|
21 #include <e32cons.h> |
|
22 |
|
23 #include "logging.h" |
|
24 #include "dbgtrcportmgr.h" |
|
25 #include "ostprotregistry.h" |
|
26 #include "portreader.h" |
|
27 #include "portwriter.h" |
|
28 #include "dbgtrcsrvsession.h" |
|
29 #include "ostmessage.h" |
|
30 #include "ostbaserouter.h" |
|
31 |
|
32 // Static functions |
|
33 |
|
34 // |
|
35 // Swap2 |
|
36 // |
|
37 // Byte-swaps a 2-byte value. Used to convert to/from little/big endian. |
|
38 // |
|
39 static TUint16 Swap2(TUint16 aSource) |
|
40 { |
|
41 TUint16 dest = 0; |
|
42 for (TInt i=0; i<2; i++) |
|
43 { |
|
44 dest <<= 8; |
|
45 dest |= aSource & 0xFF; |
|
46 aSource >>= 8; |
|
47 } |
|
48 |
|
49 return dest; |
|
50 } |
|
51 |
|
52 COstWriteMsgEntry* COstWriteMsgEntry::NewL(TDesC8& aMsg, CDbgTrcSrvSession* aMsgListener) |
|
53 { |
|
54 LOG_MSG("COstWriteMsgEntry::NewL"); |
|
55 |
|
56 COstWriteMsgEntry* self = new(ELeave) COstWriteMsgEntry(aMsgListener); |
|
57 CleanupStack::PushL(self); |
|
58 self->ConstructL(aMsg); |
|
59 CleanupStack::Pop(self); |
|
60 return self; |
|
61 } |
|
62 |
|
63 COstWriteMsgEntry::COstWriteMsgEntry(CDbgTrcSrvSession* aMsgListener) |
|
64 : iMessage(NULL), |
|
65 iWriteMsgListener(aMsgListener) |
|
66 { |
|
67 LOG_MSG("COstWriteMsgEntry::COstWriteMsgEntry"); |
|
68 |
|
69 |
|
70 } |
|
71 |
|
72 COstWriteMsgEntry::~COstWriteMsgEntry() |
|
73 { |
|
74 LOG_MSG("COstWriteMsgEntry::~COstWriteMsgEntry"); |
|
75 |
|
76 SafeDelete(iMessage); |
|
77 iWriteMsgListener = NULL; //don't delete the listener since we don't really own it. |
|
78 } |
|
79 |
|
80 void COstWriteMsgEntry::ConstructL(TDesC8& aMsg) |
|
81 { |
|
82 LOG_MSG("COstWriteMsgEntry::ConstructL"); |
|
83 |
|
84 iMessage = COstMessage::NewL(aMsg); |
|
85 } |
|
86 |
|
87 |
|
88 COstBaseRouter* COstBaseRouter::NewL() |
|
89 { |
|
90 LOG_MSG("COstWriteMsgEntry::NewL"); |
|
91 |
|
92 COstBaseRouter* self = new(ELeave) COstBaseRouter; |
|
93 CleanupStack::PushL(self); |
|
94 self->ConstructL(); |
|
95 CleanupStack::Pop(self); |
|
96 return self; |
|
97 } |
|
98 |
|
99 COstBaseRouter::COstBaseRouter() |
|
100 : iPortManager(NULL), |
|
101 iProtRegistry(NULL), |
|
102 iWriteMsgListener(NULL), |
|
103 iWriteMsgQueue(1) |
|
104 { |
|
105 LOG_MSG("COstBaseRouter::COstBaseRouter"); |
|
106 |
|
107 } |
|
108 |
|
109 COstBaseRouter::~COstBaseRouter() |
|
110 { |
|
111 LOG_MSG("COstBaseRouter::~COstBaseRouter"); |
|
112 |
|
113 SafeDelete(iPortManager); |
|
114 SafeDelete(iProtRegistry); |
|
115 |
|
116 iWriteMsgQueue.ResetAndDestroy(); |
|
117 iWriteMsgQueue.Close(); |
|
118 } |
|
119 |
|
120 void COstBaseRouter::ConstructL() |
|
121 { |
|
122 LOG_MSG("COstBaseRouter::ConstructL"); |
|
123 |
|
124 iPortManager = CDbgTrcPortMgr::NewL(); |
|
125 iProtRegistry = COstProtRegistry::NewL(); |
|
126 |
|
127 // check the target endianness |
|
128 TUint32 test; |
|
129 TUint8 *byte_alias = (TUint8 *)&test; |
|
130 |
|
131 // Write a specific 4-byte sequence and then read it as |
|
132 // a 32-bit word. Big-endian systems yield one value and |
|
133 // little-endian systems yield another. |
|
134 |
|
135 byte_alias[ 0 ] = 0x12; |
|
136 byte_alias[ 1 ] = 0x34; |
|
137 byte_alias[ 2 ] = 0x56; |
|
138 byte_alias[ 3 ] = 0x78; |
|
139 |
|
140 if (test == 0x12345678) |
|
141 iIsBigEndian = ETrue; |
|
142 else |
|
143 iIsBigEndian = EFalse; |
|
144 |
|
145 iSendMsgBuffer.Zero(); |
|
146 iRecvMsgBuffer.Zero(); |
|
147 |
|
148 iWriteMsgQueue.Reset(); |
|
149 } |
|
150 |
|
151 void COstBaseRouter::RegisterProtocol(const TOstProtIds aProtId, CDbgTrcSrvSession* aProtMsgListener, TBool aNeedHeader) |
|
152 { |
|
153 LOG_MSG("COstBaseRouter::RegisterProtocol"); |
|
154 |
|
155 iProtRegistry->RegisterProtocol(aProtId, aProtMsgListener, aNeedHeader); |
|
156 |
|
157 // Initiate the reads once someone registers a protocol. |
|
158 //ReadMessage(); |
|
159 } |
|
160 |
|
161 void COstBaseRouter::UnRegisterProtocol(const TOstProtIds aProtId) |
|
162 { |
|
163 LOG_MSG("COstBaseRouter::UnRegisterProtocol"); |
|
164 |
|
165 iProtRegistry->UnRegisterProtocol(aProtId); |
|
166 |
|
167 // if listener count is 0, cancel the reads as well. |
|
168 if (!iProtRegistry->GetProtListenerCount()) |
|
169 { |
|
170 CPortReader* reader = iPortManager->GetPortReader(); |
|
171 if (reader) |
|
172 { |
|
173 reader->Cancel(); |
|
174 } |
|
175 } |
|
176 } |
|
177 |
|
178 |
|
179 void COstBaseRouter::ReadMessage() |
|
180 { |
|
181 LOG_MSG("COstBaseRouter::ReadMessage"); |
|
182 |
|
183 CPortReader* reader = iPortManager->GetPortReader(); |
|
184 |
|
185 if (reader) |
|
186 reader->StartRead(this); |
|
187 } |
|
188 |
|
189 |
|
190 void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener) |
|
191 { |
|
192 LOG_MSG("COstBaseRouter::WriteMessage"); |
|
193 |
|
194 iSendMsgBuffer.Zero(); |
|
195 iSendMsgBuffer.Append(aMsg); |
|
196 |
|
197 DoWriteMessageL(aProtMsgListener); |
|
198 } |
|
199 |
|
200 void COstBaseRouter::WriteMessageL(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId) |
|
201 { |
|
202 LOG_MSG("COstBaseRouter::WriteMessage"); |
|
203 |
|
204 // write now, we use a fixed size array for the write message, |
|
205 // look below for the commented implementation if necessary in the future. |
|
206 iSendMsgBuffer.Zero(); |
|
207 |
|
208 TUint16 msgLength = aMsg.Length(); |
|
209 |
|
210 TUint8 version = OST_PROTOCOL_VERSION; |
|
211 |
|
212 iSendMsgBuffer.Append(&version, sizeof(TUint8)); |
|
213 iSendMsgBuffer.Append((TUint8*)&aProtId, sizeof(TUint8)); |
|
214 |
|
215 TUint16 temp = msgLength; |
|
216 if (!iIsBigEndian) |
|
217 temp = Swap2(msgLength); |
|
218 |
|
219 iSendMsgBuffer.Append((TUint8*)&temp, sizeof(TUint16)); |
|
220 |
|
221 // now append the msg data |
|
222 iSendMsgBuffer.Append(aMsg); |
|
223 |
|
224 DoWriteMessageL(aProtMsgListener); |
|
225 } |
|
226 |
|
227 |
|
228 /* |
|
229 TInt COstBaseRouter::WriteMessage(TDesC8& aMsg, CDbgTrcSrvSession* aProtMsgListener, TOstProtIds aProtId) |
|
230 { |
|
231 HBufC8* msgBuffer = HBufC8::New(aMsg.Length() + OST_HEADER_LENGTH); |
|
232 |
|
233 TUint16 msgLength = aMsg.Length(); |
|
234 |
|
235 TUint8 version = OST_PROTOCOL_VERSION; |
|
236 |
|
237 msgBuffer->Des().Append(&version, sizeof(TUint8)); |
|
238 msgBuffer->Des().Append((TUint8*)&aProtId, sizeof(TUint8)); |
|
239 |
|
240 TUint16 temp = msgLength; |
|
241 if (!iIsBigEndian) |
|
242 temp = Swap2(msgLength); |
|
243 |
|
244 msgBuffer->Des().Append((TUint8*)&temp, sizeof(TUint16)); |
|
245 |
|
246 // now append the msg data |
|
247 msgBuffer->Des().Append(aMsg); |
|
248 |
|
249 |
|
250 } |
|
251 */ |
|
252 |
|
253 void COstBaseRouter::DoWriteMessageL(CDbgTrcSrvSession* aProtMsgListener) |
|
254 { |
|
255 LOG_MSG("COstBaseRouter::DoWriteMessage"); |
|
256 |
|
257 CPortWriter* writer = iPortManager->GetPortWriter(); |
|
258 |
|
259 if(writer) |
|
260 { |
|
261 if (writer->IsBusy()) |
|
262 { |
|
263 LOG_MSG("Writer busy, queuing up the write message"); |
|
264 |
|
265 // we are already writing a message |
|
266 // so queue up this one, we only have to queue up one message for each connected client for writing. |
|
267 COstWriteMsgEntry* writeMsgEntry = COstWriteMsgEntry::NewL(iSendMsgBuffer, aProtMsgListener); |
|
268 iWriteMsgQueue.Append(writeMsgEntry); |
|
269 } |
|
270 else |
|
271 { |
|
272 // set the write listener for completing the request when the write is done |
|
273 iWriteMsgListener = aProtMsgListener; |
|
274 writer->StartWrite(iSendMsgBuffer, this); |
|
275 } |
|
276 } |
|
277 } |
|
278 |
|
279 void COstBaseRouter::DataAvailable(TDesC8& aMsgData, TUint aLength) |
|
280 { |
|
281 LOG_MSG("COstBaseRouter::DataAvailable"); |
|
282 LOG_MSG2("Received bytes : %d", aLength); |
|
283 |
|
284 TInt remainingBytes = aMsgData.Length(); |
|
285 const TUint8* recvMsgDataPtr = aMsgData.Ptr(); |
|
286 while (remainingBytes > 0) |
|
287 { |
|
288 TInt bytesToCopy = remainingBytes; |
|
289 TInt spaceAvailable = MAX_BUF_SIZE-iRecvMsgBuffer.Length(); |
|
290 if (spaceAvailable == 0) //should never happen, if this happens, then we will loose messages. |
|
291 return; |
|
292 |
|
293 if (remainingBytes > spaceAvailable) |
|
294 { |
|
295 bytesToCopy = spaceAvailable; |
|
296 } |
|
297 |
|
298 remainingBytes -= bytesToCopy; |
|
299 iRecvMsgBuffer.Append(recvMsgDataPtr, bytesToCopy); |
|
300 recvMsgDataPtr += bytesToCopy; |
|
301 |
|
302 LOG_MSG2("Bytes copied: %d", bytesToCopy); |
|
303 LOG_MSG2("Remaining bytes : %d", remainingBytes); |
|
304 |
|
305 // |
|
306 // We could possibly get more than one message at a time, |
|
307 // so check until we have atleast as many bytes as the OST header. |
|
308 // |
|
309 LOG_MSG2("Total bytes in the buffer : %d", iRecvMsgBuffer.Length()); |
|
310 while (iRecvMsgBuffer.Length() > OST_HEADER_LENGTH) |
|
311 { |
|
312 LOG_MSG("No of received bytes > OST header length"); |
|
313 |
|
314 const TUint8* ptr = iRecvMsgBuffer.Ptr(); |
|
315 |
|
316 TUint8 version = ptr[VERS_FIELD_INDEX]; |
|
317 TUint8 protId = ptr[PROTID_FIELD_INDEX]; |
|
318 |
|
319 // There could be some junk bytes in the data. |
|
320 // With the latest PCSuite/USB cable drivers, there seems to be some |
|
321 // junk bytes in the USB channel. Also we can only do this simple check |
|
322 // only at the beginning of the packet. The only check we have right now |
|
323 // for the OST base protocol is to check for the version and the protocol id |
|
324 if ( !( (version == OST_PROTOCOL_VERSION || version == OST_VERSION_PROTOCOL_VERSION) && |
|
325 (protId == EOstProtTrk || protId == EOstProtTraceCore || protId == EOstProtOstSystem || protId == EOstProtTrcActivation) ) ) |
|
326 { |
|
327 LOG_MSG2("Invalid version byte: %x", version); |
|
328 LOG_MSG2("Invalid protocol byte: %x", protId); |
|
329 RemoveNonOstBytes(iRecvMsgBuffer); |
|
330 } |
|
331 |
|
332 LOG_MSG2("Total bytes in the buffer after removing non ost : %d", iRecvMsgBuffer.Length()); |
|
333 if (iRecvMsgBuffer.Length()>OST_HEADER_LENGTH) |
|
334 { |
|
335 // reset ptr just incase if we have deleted some junk bytes |
|
336 ptr = iRecvMsgBuffer.Ptr(); |
|
337 TUint16 packetLength = 0; |
|
338 SwapBytes((TUint8*)&packetLength, &ptr[LENGTH_FIELD_INDEX], 2); |
|
339 |
|
340 LOG_MSG2("packet length is %d", packetLength); |
|
341 |
|
342 if (iRecvMsgBuffer.Length() >= (packetLength+OST_HEADER_LENGTH)) |
|
343 { |
|
344 LOG_MSG("Got one complete message"); |
|
345 |
|
346 // got one complete message, complete the message if someone is listening for this message. |
|
347 TBool needHeader; |
|
348 CDbgTrcSrvSession* protMsgListener = iProtRegistry->GetProtListenerForProtId((TOstProtIds)protId, needHeader); |
|
349 |
|
350 if (protMsgListener) |
|
351 { |
|
352 LOG_MSG("Found a listener"); |
|
353 |
|
354 TPtrC8 completeMessage; |
|
355 // check to see if we need to strip the header or not. |
|
356 if (needHeader) |
|
357 completeMessage.Set(iRecvMsgBuffer.Ptr(), packetLength+OST_HEADER_LENGTH); |
|
358 else |
|
359 completeMessage.Set(iRecvMsgBuffer.Ptr()+OST_HEADER_LENGTH, packetLength); |
|
360 |
|
361 TRAPD(err, protMsgListener->MessageAvailableL(completeMessage)); |
|
362 if (err != KErrNone) |
|
363 LOG_MSG2("Failed to deliver the message: %d", err); |
|
364 } |
|
365 |
|
366 LOG_MSG2("Deleting bytes in the recieve buffer: %d", packetLength+OST_HEADER_LENGTH); |
|
367 |
|
368 // now remove this message from our buffer as its already given to the listener |
|
369 iRecvMsgBuffer.Delete(0, packetLength+OST_HEADER_LENGTH); |
|
370 |
|
371 LOG_MSG2("Remaining bytes in the recieve buffer: %d", iRecvMsgBuffer.Length()); |
|
372 } |
|
373 else |
|
374 { |
|
375 // We have more bytes than the header but we have an incomplete message. |
|
376 // So we break out here. |
|
377 break; |
|
378 } |
|
379 } |
|
380 } |
|
381 } |
|
382 } |
|
383 |
|
384 void COstBaseRouter::DataWriteComplete(TInt aErrCode) |
|
385 { |
|
386 LOG_MSG("COstBaseRouter::DataWriteComplete"); |
|
387 |
|
388 if (iWriteMsgListener != NULL) |
|
389 { |
|
390 iWriteMsgListener->WriteComplete(aErrCode); |
|
391 iWriteMsgListener = NULL; |
|
392 } |
|
393 else |
|
394 { |
|
395 LOG_MSG("Invalid write message listener, should never happen"); |
|
396 } |
|
397 |
|
398 if (iWriteMsgQueue.Count() > 0) |
|
399 { |
|
400 LOG_MSG("Message found in write queue"); |
|
401 |
|
402 COstMessage* ostMsg = iWriteMsgQueue[0]->iMessage; |
|
403 iWriteMsgListener = iWriteMsgQueue[0]->iWriteMsgListener; |
|
404 HBufC8* msg = ostMsg->iMsgBuffer; |
|
405 |
|
406 CPortWriter* writer = iPortManager->GetPortWriter(); |
|
407 if(writer) |
|
408 writer->StartWrite(*msg, this); |
|
409 |
|
410 // now remove the message from the queue |
|
411 SafeDelete(iWriteMsgQueue[0]); |
|
412 iWriteMsgQueue.Remove(0); |
|
413 } |
|
414 } |
|
415 |
|
416 void COstBaseRouter::GetPortConfig(TDes8& aConfigDes) |
|
417 { |
|
418 LOG_MSG("COstBaseRouter::GetPortConfig"); |
|
419 |
|
420 iPortManager->GetPortConfig(aConfigDes); |
|
421 } |
|
422 |
|
423 TInt COstBaseRouter::SetPortConfig(TDesC8& aConfigDes) |
|
424 { |
|
425 LOG_MSG("COstBaseRouter::SetPortConfig"); |
|
426 |
|
427 return iPortManager->SetPortConfig(aConfigDes); |
|
428 } |
|
429 |
|
430 TInt COstBaseRouter::OpenCommPortL() |
|
431 { |
|
432 LOG_MSG("COstBaseRouter::OpenCommPort"); |
|
433 |
|
434 return iPortManager->OpenPortL(); |
|
435 } |
|
436 |
|
437 TInt COstBaseRouter::CloseCommPort() |
|
438 { |
|
439 LOG_MSG("COstBaseRouter::CloseCommPort"); |
|
440 |
|
441 return iPortManager->ClosePort(); |
|
442 } |
|
443 |
|
444 |
|
445 void COstBaseRouter::SwapBytes(TUint8* aTrgtData, const TUint8* aSrcData, TInt aLength) |
|
446 { |
|
447 LOG_MSG("COstBaseRouter::SwapBytes"); |
|
448 |
|
449 if (iIsBigEndian) |
|
450 { |
|
451 Mem::Copy(aTrgtData, aSrcData, aLength); |
|
452 } |
|
453 else |
|
454 { |
|
455 for (int i=aLength-1, j=0; i>=0; i--, j++) |
|
456 aTrgtData[j] = aSrcData[i]; |
|
457 } |
|
458 } |
|
459 |
|
460 |
|
461 void COstBaseRouter::RemoveNonOstBytes(TDes8& aMsgBuffer) |
|
462 { |
|
463 LOG_MSG("COstBaseRouter::RemoveNonOstBytes"); |
|
464 // We need to check for non OST bytes only in the beginning of the packet. |
|
465 // The only check we have right now for the OST base protocol |
|
466 // is to check for the version and the protocol id |
|
467 const TUint8* msgDataPtr = aMsgBuffer.Ptr(); |
|
468 // look for the version byte.. |
|
469 // if found, bail out and check for protocol byte |
|
470 TUint length = aMsgBuffer.Length(); |
|
471 LOG_MSG2("Total bytes in the buffer: %d", length); |
|
472 for (TInt i=VERS_FIELD_INDEX; i<length; i++) |
|
473 { |
|
474 if (msgDataPtr[VERS_FIELD_INDEX] == OST_PROTOCOL_VERSION || |
|
475 msgDataPtr[VERS_FIELD_INDEX] == OST_VERSION_PROTOCOL_VERSION) |
|
476 { |
|
477 // If we have more than one byte and the first byte seems to be the version byte |
|
478 // then check to see whether the second byte is the protocol byte or not. |
|
479 // if not, then delete the two bytes and start looking for version byte in the remaining bytes |
|
480 if (aMsgBuffer.Length()>1) |
|
481 { |
|
482 if (msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrk || |
|
483 msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTraceCore || |
|
484 msgDataPtr[PROTID_FIELD_INDEX] == EOstProtOstSystem || |
|
485 msgDataPtr[PROTID_FIELD_INDEX] == EOstProtTrcActivation) |
|
486 { |
|
487 LOG_MSG("Found a valid packet"); |
|
488 break; |
|
489 } |
|
490 else |
|
491 { |
|
492 // we didn't find the version byte and the protocol byte together |
|
493 // so delete the two bytes |
|
494 LOG_MSG2("Deleting junk bytes, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]); |
|
495 LOG_MSG2("Deleting junk bytes, unexpected protocol id: %x", msgDataPtr[PROTID_FIELD_INDEX]); |
|
496 |
|
497 aMsgBuffer.Delete(VERS_FIELD_INDEX, 2); |
|
498 i++; //deleting more than one byte, so increment one more time here. |
|
499 } |
|
500 } |
|
501 else |
|
502 { |
|
503 // Special case handling when there is only one remaining byte |
|
504 // and that byte happens to be the version byte |
|
505 // This could be an invalid byte from out of protocol data, just happens to be the version byte. |
|
506 // So delete this byte as well just so that we don't treat this byte as the version byte by mistake. |
|
507 LOG_MSG2("Deleting one remaining byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]); |
|
508 aMsgBuffer.Delete(VERS_FIELD_INDEX, 1); |
|
509 } |
|
510 } |
|
511 else |
|
512 { |
|
513 // if the first byte is not the version byte, delete it |
|
514 // it could be out of protocol data, we just need throw away |
|
515 LOG_MSG2("Deleting junk byte, unexpected version: %x", msgDataPtr[VERS_FIELD_INDEX]); |
|
516 aMsgBuffer.Delete(VERS_FIELD_INDEX, 1); |
|
517 } |
|
518 } |
|
519 } |