kerneltest/e32test/misc/ymodemtx.cpp
branchRCL_3
changeset 256 c1f20ce4abcf
equal deleted inserted replaced
249:a179b74831c9 256:c1f20ce4abcf
       
     1 // Copyright (c) 2009-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\misc\ymodemtx.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32std.h>
       
    19 #include <e32svr.h>
       
    20 #include <f32file.h>
       
    21 #include <d32comm.h>
       
    22 
       
    23 RFs TheFs;
       
    24 RFile TheFile;
       
    25 TInt FileSize;
       
    26 RBusDevComm TheComm;
       
    27 RTimer TheTimer;
       
    28 TFileName FileName;
       
    29 TFileName FileName8b;
       
    30 TPtr8 FileName8(0,0,0);
       
    31 
       
    32 const TUint8 STX=0x02;
       
    33 const TUint8 EOT=0x04;
       
    34 const TUint8 ACK=0x06;
       
    35 const TUint8 BIGC=0x43;
       
    36 const TUint8 BIGG=0x47;
       
    37 
       
    38 #define PACKET_SIZE		1024
       
    39 
       
    40 #define MIN(a,b)		((a)<(b)?(a):(b))
       
    41 #define OFFSET(p,off)	((void*)((char*)p+off))
       
    42 
       
    43 #define RESET_COMM()	TheComm.ResetBuffers()
       
    44 
       
    45 #define assert(x)			((void)( (x) || (__Panic(__LINE__, #x),0) ))
       
    46 #define assert_KErrNone(r)	((void)( ((r)==KErrNone) || (__Panic(__LINE__, (r)),0) ))
       
    47 
       
    48 
       
    49 void __Panic(TInt aLine, TInt aError)
       
    50 	{
       
    51 	RDebug::Printf("Line %d Expected KErrNone got %d", aLine, aError);
       
    52 	User::Panic(_L("YMODEMTX"), aLine);
       
    53 	}
       
    54 
       
    55 void __Panic(TInt aLine, const char* aMessage)
       
    56 	{
       
    57 	RDebug::Printf("Line %d Assertion \"%s\" failed", aLine, aMessage);
       
    58 	User::Panic(_L("YMODEMTX"), aLine);
       
    59 	}
       
    60 
       
    61 /*
       
    62 YModem packet structure:
       
    63 Byte 0 = STX
       
    64 Byte 1 = sequence number (first user data packet is 1)
       
    65 Byte 2 = complement of sequence number
       
    66 Bytes 3-1026 = data (1K per packet)
       
    67 Bytes 1027, 1028 = 16-bit CRC (big-endian)
       
    68 
       
    69 A herald packet is sent first, with sequence number 0
       
    70 The data field consists of the null-terminated file name
       
    71 followed by the null-terminated file size in ASCII decimal
       
    72 digits.
       
    73 */
       
    74 struct SPacket
       
    75 	{
       
    76 	TUint8 iPTI;
       
    77 	TUint8 iSeq;
       
    78 	TUint8 iSeqBar;
       
    79 	TUint8 iData[PACKET_SIZE];
       
    80 	TUint8 iCRC1;
       
    81 	TUint8 iCRC0;
       
    82 	};
       
    83 
       
    84 static const TUint16 crcTab[256] =
       
    85     {
       
    86 	0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a,
       
    87 	0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,
       
    88 	0x72f7,0x62d6,0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,0x2462,
       
    89 	0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,0xa56a,0xb54b,0x8528,0x9509,
       
    90 	0xe5ee,0xf5cf,0xc5ac,0xd58d,0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,
       
    91 	0x46b4,0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,0x48c4,0x58e5,
       
    92 	0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,
       
    93 	0x9969,0xa90a,0xb92b,0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
       
    94 	0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,0x6ca6,0x7c87,0x4ce4,
       
    95 	0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,
       
    96 	0x8d68,0x9d49,0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,0xff9f,
       
    97 	0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,0x9188,0x81a9,0xb1ca,0xa1eb,
       
    98 	0xd10c,0xc12d,0xf14e,0xe16f,0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,
       
    99 	0x6067,0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,0x02b1,0x1290,
       
   100 	0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,
       
   101 	0xe54f,0xd52c,0xc50d,0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
       
   102 	0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,0x26d3,0x36f2,0x0691,
       
   103 	0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,
       
   104 	0xb98a,0xa9ab,0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,0xcb7d,
       
   105 	0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16,
       
   106 	0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,
       
   107 	0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,0xef1f,0xff3e,
       
   108 	0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,
       
   109 	0x3eb2,0x0ed1,0x1ef0
       
   110     };
       
   111 
       
   112 void UpdateCrc(const void* aPtr, TInt aLength, TUint16& aCrc)
       
   113 //
       
   114 // Perform a CCITT CRC checksum.
       
   115 //
       
   116 	{
       
   117 
       
   118 	register const TUint8* pB = (const TUint8*)aPtr;
       
   119 	register TUint16 crc=aCrc;
       
   120     while (aLength--)
       
   121 		crc=TUint16((crc<<8)^crcTab[(crc>>8)^*pB++]);
       
   122 	aCrc=crc;
       
   123 	}
       
   124 
       
   125 void ClearCommError()
       
   126 	{
       
   127 	}
       
   128 
       
   129 TInt CommRead1(TInt aTimeout)
       
   130 	{
       
   131 	TBuf8<1> c;
       
   132 	TRequestStatus s0, s1;
       
   133 	TheComm.ReadOneOrMore(s1, c);
       
   134 	TheTimer.After(s0, aTimeout*1000);
       
   135 	User::WaitForRequest(s0, s1);
       
   136 	if (s1 != KRequestPending)
       
   137 		{
       
   138 		TheTimer.Cancel();
       
   139 		User::WaitForRequest(s0);
       
   140 		return (s1==KErrNone) ? c[0] : s1.Int();
       
   141 		}
       
   142 	TheComm.ReadCancel();
       
   143 	User::WaitForRequest(s1);
       
   144 	return KErrTimedOut;
       
   145 	}
       
   146 
       
   147 TInt CommRead(TDes8& aBuf, TInt aTimeout)
       
   148 	{
       
   149 	aBuf.Zero();
       
   150 	TRequestStatus s0, s1;
       
   151 	TInt timeout = aTimeout * 1000;
       
   152 
       
   153 	TUint8* b = (TUint8*)aBuf.Ptr();
       
   154 	while (aBuf.Length() < aBuf.MaxLength())
       
   155 		{
       
   156 		TPtr8 p(b+aBuf.Length(), 0, aBuf.MaxLength()-aBuf.Length());
       
   157 		TheComm.ReadOneOrMore(s1, p);
       
   158 		TheTimer.After(s0, timeout);
       
   159 		User::WaitForRequest(s0, s1);
       
   160 		if (s1 == KErrNone)
       
   161 			{
       
   162 			TheTimer.Cancel();
       
   163 			User::WaitForRequest(s0);
       
   164 			aBuf.SetLength(aBuf.Length() + p.Length());
       
   165 			timeout = 500000;
       
   166 			continue;
       
   167 			}
       
   168 		if (s1 != KRequestPending)
       
   169 			{
       
   170 			TheTimer.Cancel();
       
   171 			User::WaitForRequest(s0);
       
   172 			break;
       
   173 			}
       
   174 		if (s0 != KRequestPending)
       
   175 			{
       
   176 			TheComm.ReadCancel();
       
   177 			User::WaitForRequest(s1);
       
   178 			break;
       
   179 			}
       
   180 		}
       
   181 	if (aBuf.Length()==0)
       
   182 		return KErrTimedOut;
       
   183 	return aBuf.Length();
       
   184 	}
       
   185 
       
   186 void CommWrite(const TDesC8& aBuf)
       
   187 	{
       
   188 	TRequestStatus s;
       
   189 	TheComm.Write(s, aBuf);
       
   190 	User::WaitForRequest(s);
       
   191 	}
       
   192 
       
   193 void CommWriteC(TUint aChar)
       
   194 	{
       
   195 	TBuf8<1> b;
       
   196 	b.SetLength(1);
       
   197 	b[0] = (TUint8)aChar;
       
   198 	CommWrite(b);
       
   199 	}
       
   200 
       
   201 void CommWriteS(const char* aString)
       
   202 	{
       
   203 	CommWrite(TPtrC8((const TUint8*)aString));
       
   204 	}
       
   205 
       
   206 TInt PreparePacket(SPacket& pkt, TInt aSeq)
       
   207 	{
       
   208 	TInt r = KErrNone;
       
   209 	TUint16 crc = 0;
       
   210 
       
   211 	pkt.iPTI = STX;
       
   212 	pkt.iSeq = (TUint8)(aSeq>=0 ? aSeq : 0);
       
   213 	pkt.iSeqBar = (TUint8)~pkt.iSeq;
       
   214 	if (aSeq>0)
       
   215 		{
       
   216 		TInt l;
       
   217 		TInt fpos = (aSeq-1)*PACKET_SIZE;	// file position of packet
       
   218 		if ( fpos >= FileSize )
       
   219 			return KErrEof;
       
   220 		l = MIN(PACKET_SIZE, FileSize-fpos);
       
   221 		TPtr8 d(pkt.iData, 0, l);
       
   222 		assert_KErrNone(TheFile.Read(d));
       
   223 		if (l<PACKET_SIZE)
       
   224 			memset(pkt.iData+l, 0, PACKET_SIZE-l);
       
   225 		}
       
   226 	else
       
   227 		{
       
   228 		memset(pkt.iData, 0, PACKET_SIZE);
       
   229 		if (aSeq==0)
       
   230 			{
       
   231 			TInt pos = FileName8.LocateReverse('\\');
       
   232 			TPtrC8 fn8(FileName8.Mid(pos+1));
       
   233 			memcpy(pkt.iData, fn8.Ptr(), fn8.Length());
       
   234 			TPtr8 d2(pkt.iData+fn8.Length()+1, 0, PACKET_SIZE-fn8.Length()-1);
       
   235 			d2.Num(FileSize);
       
   236 			}
       
   237 		}
       
   238 	UpdateCrc(pkt.iData, PACKET_SIZE, crc);
       
   239 	pkt.iCRC1 = (TUint8)(crc>>8);
       
   240 	pkt.iCRC0 = (TUint8)crc;
       
   241 	return r;
       
   242 	}
       
   243 
       
   244 TInt SendPacket(TInt& aSeq, TBool aStream)
       
   245 	{
       
   246 	TInt c;
       
   247 	SPacket pkt;
       
   248 	TInt retries = 10;
       
   249 	TInt tmout = (aSeq>=0) ? 2000 : 500;
       
   250 	TInt r = PreparePacket(pkt, aSeq);
       
   251 	if (r!=KErrNone)
       
   252 		return r;
       
   253 	for(;;)
       
   254 		{
       
   255 		RESET_COMM();
       
   256 		CommWrite(TPtrC8( (const TUint8*)&pkt, sizeof(pkt) ));
       
   257 		if (aStream)
       
   258 			break;
       
   259 		c = CommRead1(tmout);
       
   260 		if (c==KErrTimedOut && aSeq<0)
       
   261 			return KErrNone;
       
   262 		if (c>=0)
       
   263 			{
       
   264 			if (c==ACK)
       
   265 				break;
       
   266 			}
       
   267 		if (--retries==0)
       
   268 			return KErrTimedOut;
       
   269 		}
       
   270 	if (aSeq==0)
       
   271 		{
       
   272 		c = CommRead1(100);
       
   273 		if (c==KErrTimedOut)
       
   274 			{
       
   275 			++aSeq;
       
   276 			return KErrNone;
       
   277 			}
       
   278 		if (aStream && c!=BIGG)
       
   279 			return KErrTimedOut;
       
   280 		else if (!aStream && c!=BIGC)
       
   281 			return KErrTimedOut;
       
   282 		}
       
   283 	++aSeq;
       
   284 	return r;
       
   285 	}
       
   286 
       
   287 TInt SendImageFile()
       
   288 	{
       
   289 	TInt r = 0;
       
   290 	TInt b1;
       
   291 	TBool stream;
       
   292 	TInt seq = 0;
       
   293 
       
   294 	RESET_COMM();
       
   295 	r = CommRead1(20000);
       
   296 	if (r<0)
       
   297 		return r;
       
   298 	if (r!=BIGG && r!=BIGC)
       
   299 		return KErrTimedOut;
       
   300 	stream = (r==BIGG);
       
   301 	seq = 0;
       
   302 	r = KErrNone;
       
   303 	while (r==KErrNone)
       
   304 		{
       
   305 		r = SendPacket(seq, stream);
       
   306 		}
       
   307 	if (r!=KErrEof)
       
   308 		return r;
       
   309 	r=KErrNone;
       
   310 	RESET_COMM();
       
   311 	CommWriteC(EOT);
       
   312 	b1 = CommRead1(500);
       
   313 	if (b1==KErrTimedOut)
       
   314 		return KErrNone;
       
   315 	if (b1!=ACK)
       
   316 		return KErrNone;
       
   317 	b1 = CommRead1(1000);
       
   318 	if (b1==KErrTimedOut)
       
   319 		return KErrNone;
       
   320 	if (stream && b1!=BIGG)
       
   321 		return KErrNone;
       
   322 	else if (!stream && b1!=BIGC)
       
   323 		return KErrNone;
       
   324 	seq = -1;
       
   325 	r = SendPacket(seq, stream);
       
   326 	return r;
       
   327 	}
       
   328 
       
   329 
       
   330 #define	ALLOWBPS(x)	case x : bps = EBps##x; break
       
   331 
       
   332 void ParseCommandLine()
       
   333 	{
       
   334 	TInt r = 0;
       
   335 	TInt cmdLineLen = User::CommandLineLength();
       
   336 	HBufC* cmdLine = HBufC::New(cmdLineLen);
       
   337 	assert(cmdLine!=0);
       
   338 	TPtr cmdLineW(cmdLine->Des());
       
   339 	User::CommandLine(cmdLineW);
       
   340 	TLex16 cmdLineLex(*cmdLine);
       
   341 	TInt baud = 115200;
       
   342 	TInt port = 0;
       
   343 	while (!cmdLineLex.Eos())
       
   344 		{
       
   345 		TPtrC token(cmdLineLex.NextToken());
       
   346 		cmdLineLex.SkipSpace();
       
   347 		if (token[0]=='-')
       
   348 			{
       
   349 			switch (token[1])
       
   350 				{
       
   351 				case 'p':
       
   352 					{
       
   353 					r = cmdLineLex.Val(port);
       
   354 					assert_KErrNone(r);
       
   355 					break;
       
   356 					}
       
   357 				case 'b':
       
   358 					{
       
   359 					r = cmdLineLex.Val(baud);
       
   360 					assert_KErrNone(r);
       
   361 					break;
       
   362 					}
       
   363 				default:
       
   364 					assert(0);
       
   365 					break;
       
   366 				}
       
   367 			continue;
       
   368 			}
       
   369 		FileName = token;
       
   370 		assert(cmdLineLex.Eos());
       
   371 		}
       
   372 	assert(FileName.Length()>0);
       
   373 
       
   374 	TBps bps = EBpsSpecial;
       
   375 	switch (baud)
       
   376 		{
       
   377 		ALLOWBPS(50);
       
   378 		ALLOWBPS(75);
       
   379 		ALLOWBPS(110);
       
   380 		ALLOWBPS(134);
       
   381 		ALLOWBPS(150);
       
   382 		ALLOWBPS(300);
       
   383 		ALLOWBPS(600);
       
   384 		ALLOWBPS(1200);
       
   385 		ALLOWBPS(1800);
       
   386 		ALLOWBPS(2000);
       
   387 		ALLOWBPS(2400);
       
   388 		ALLOWBPS(3600);
       
   389 		ALLOWBPS(4800);
       
   390 		ALLOWBPS(7200);
       
   391 		ALLOWBPS(9600);
       
   392 		ALLOWBPS(19200);
       
   393 		ALLOWBPS(38400);
       
   394 		ALLOWBPS(57600);
       
   395 		ALLOWBPS(115200);
       
   396 		ALLOWBPS(230400);
       
   397 		ALLOWBPS(460800);
       
   398 		ALLOWBPS(576000);
       
   399 		ALLOWBPS(1152000);
       
   400 		ALLOWBPS(4000000);
       
   401 		ALLOWBPS(921600);
       
   402 		}
       
   403 	assert(bps != EBpsSpecial);
       
   404 
       
   405 	assert_KErrNone(TheFs.Connect());
       
   406 	assert_KErrNone(TheFile.Open(TheFs, FileName, EFileShareReadersOnly|EFileRead));
       
   407 	assert_KErrNone(TheFile.Size(FileSize));
       
   408 	FileName8b = FileName;
       
   409 	new (&FileName8) TPtr8(FileName8b.Collapse());
       
   410 	assert(TheComm.Open(port)==KErrNone);
       
   411 	TCommConfig cfgBuf;
       
   412 	TCommConfigV01& cfg = cfgBuf();
       
   413 	cfg.iRate = bps;
       
   414 	cfg.iDataBits = EData8;
       
   415 	cfg.iStopBits = EStop1;
       
   416 	cfg.iParity = EParityNone;
       
   417 	cfg.iHandshake = 0;
       
   418 	cfg.iParityError = 0;
       
   419 	cfg.iFifo = EFifoEnable;
       
   420 	cfg.iSpecialRate = 0;
       
   421 	cfg.iTerminatorCount = 0;
       
   422 	cfg.iSIREnable = ESIRDisable;
       
   423 	cfg.iSIRSettings = KConfigSIRShutDown;
       
   424 	assert_KErrNone(TheComm.SetConfig(cfgBuf));
       
   425 	CommWrite(_L8("Sending "));
       
   426 	CommWrite(FileName8);
       
   427 	CommWrite(_L8("\r\nWaiting for YModem or YModem-G receive...\r\n"));
       
   428 	}
       
   429 
       
   430 _LIT(KLddName,"ECOMM");
       
   431 _LIT(KPddName,"EUART");
       
   432 
       
   433 void LoadCommDrivers()
       
   434 	{
       
   435 	TInt r=User::LoadLogicalDevice(KLddName);
       
   436 	if (r!=KErrAlreadyExists)
       
   437 		assert_KErrNone(r);
       
   438 
       
   439 	TInt i;
       
   440 	TInt n=0;
       
   441 	for (i=-1; i<10; ++i)
       
   442 		{
       
   443 		TBuf<16> pddName=KPddName();
       
   444 		if (i>=0)
       
   445 			pddName.Append('0'+i);
       
   446 		r=User::LoadPhysicalDevice(pddName);
       
   447 		if (r==KErrNone || r==KErrAlreadyExists)
       
   448 			++n;
       
   449 		}
       
   450 	assert(n!=0);
       
   451 	}
       
   452 
       
   453 TInt E32Main()
       
   454 	{
       
   455 	TInt r;
       
   456 
       
   457 	LoadCommDrivers();
       
   458 	ParseCommandLine();
       
   459 
       
   460 	r = TheTimer.CreateLocal();
       
   461 	assert_KErrNone(r);
       
   462 
       
   463 	r = SendImageFile();
       
   464 	assert_KErrNone(r);
       
   465 
       
   466 	TheTimer.Close();
       
   467 	TheComm.Close();
       
   468 	TheFile.Close();
       
   469 	TheFs.Close();
       
   470 
       
   471 	return KErrNone;
       
   472 	}