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: ECOM plugin for communication over serial port |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <badesca.h> |
|
21 #include <f32file.h> |
|
22 |
|
23 #include "HtiSerialCommEcomPlugin.h" |
|
24 #include <HtiCfg.h> |
|
25 #include <HtiLogging.h> |
|
26 |
|
27 // CONSTANTS |
|
28 _LIT( KHtiSerialError, "HtiSerialError" ); |
|
29 _LIT( KHtiOkButton, "OK" ); |
|
30 |
|
31 _LIT( KHtiCfgPath, "\\" ); // root of drive |
|
32 _LIT( KHtiSerialCommCfg, "HTISerialComm.cfg" ); |
|
33 _LIT8( KCommPortNumber, "CommPort" ); |
|
34 _LIT8( KDataRate, "DataRate" ); |
|
35 _LIT8( KParity, "Parity" ); |
|
36 _LIT8( KDataBits, "DataBits" ); |
|
37 _LIT8( KStopBits, "StopBits" ); |
|
38 _LIT8( KSendDelay, "SendDelay" ); |
|
39 _LIT8( KHandshake, "Handshake" ); |
|
40 |
|
41 #if defined (__WINS__) |
|
42 _LIT( SERIAL_PDD_NAME, "ECDRV" ); |
|
43 #else |
|
44 _LIT( SERIAL_PDD_NAME, "EUART1" ); |
|
45 #endif |
|
46 _LIT( SERIAL_LDD_NAME, "ECOMM" ); |
|
47 _LIT( RS232_CSY_NAME, "ECUART" ); |
|
48 |
|
49 const static TUint KReceiveBufferLength = 4*1024; |
|
50 const static TUint KSendBufferLength = 4*1024; |
|
51 const static TInt KMaxCommPortNumber = 99; |
|
52 const static TInt KMaxHtiNotifierLength = 128; |
|
53 |
|
54 CHtiSerialCommEcomPlugin* CHtiSerialCommEcomPlugin::NewL() |
|
55 { |
|
56 HTI_LOG_FUNC_IN( "Serial::NewL" ); |
|
57 CHtiSerialCommEcomPlugin* plugin = new (ELeave) CHtiSerialCommEcomPlugin(); |
|
58 CleanupStack::PushL( plugin ); |
|
59 plugin->ConstructL(); |
|
60 CleanupStack::Pop( plugin ); |
|
61 HTI_LOG_FUNC_OUT( "Serial::NewL" ); |
|
62 return plugin; |
|
63 } |
|
64 |
|
65 CHtiSerialCommEcomPlugin::~CHtiSerialCommEcomPlugin() |
|
66 { |
|
67 HTI_LOG_FUNC_IN( "Serial::~CHtiSerialCommEcomPlugin" ); |
|
68 iCommPort.Close(); |
|
69 iCommServ.Close(); |
|
70 delete iCfg; |
|
71 User::FreeLogicalDevice( SERIAL_LDD_NAME ); |
|
72 User::FreePhysicalDevice( SERIAL_PDD_NAME ); |
|
73 HTI_LOG_FUNC_OUT( "Serial::~CHtiSerialCommEcomPlugin" ); |
|
74 } |
|
75 |
|
76 CHtiSerialCommEcomPlugin::CHtiSerialCommEcomPlugin() |
|
77 { |
|
78 // default port settings |
|
79 iPortNumber = 0; |
|
80 iDataRate = EBps115200; |
|
81 iParity = EParityNone; |
|
82 iDataBits = EData8; |
|
83 iStopBits = EStop1; |
|
84 |
|
85 iSendDelay = 0; |
|
86 iHandshake = 0; |
|
87 } |
|
88 |
|
89 void CHtiSerialCommEcomPlugin::ConstructL() |
|
90 { |
|
91 TRAPD( err, LoadConfigL() ); |
|
92 if ( err == KErrNone ) |
|
93 { |
|
94 ReadConfig(); |
|
95 } |
|
96 InitCommServerL(); |
|
97 InitCommPortL(); |
|
98 } |
|
99 |
|
100 void CHtiSerialCommEcomPlugin::LoadConfigL() |
|
101 { |
|
102 HTI_LOG_FUNC_IN( "Serial::LoadConfigL" ); |
|
103 iCfg = CHtiCfg::NewL(); |
|
104 HTI_LOG_TEXT( "CHtiCfg constructed - loading cfg file" ); |
|
105 iCfg->LoadCfgL( KHtiCfgPath, KHtiSerialCommCfg ); |
|
106 HTI_LOG_TEXT( "Cfg file loaded" ); |
|
107 HTI_LOG_FUNC_OUT( "Serial::LoadConfigL" ); |
|
108 } |
|
109 |
|
110 void CHtiSerialCommEcomPlugin::ReadConfig() |
|
111 { |
|
112 HTI_LOG_FUNC_IN( "Serial::ReadConfig" ); |
|
113 |
|
114 TInt portNumberCfg = 0; |
|
115 TRAPD( paramErr, |
|
116 portNumberCfg = iCfg->GetParameterIntL( KCommPortNumber ) ); |
|
117 if ( paramErr != KErrNone ) |
|
118 { |
|
119 HTI_LOG_FORMAT( |
|
120 "ComPort not defined in cfg, using default value %d", |
|
121 iPortNumber ); |
|
122 portNumberCfg = iPortNumber; |
|
123 } |
|
124 if ( portNumberCfg > KMaxCommPortNumber || portNumberCfg < 0 ) |
|
125 { |
|
126 HTI_LOG_FORMAT( "Unsupported ComPort %d defined in cfg, using default", |
|
127 portNumberCfg ); |
|
128 portNumberCfg = iPortNumber; |
|
129 } |
|
130 iPortNumber = portNumberCfg; |
|
131 |
|
132 TInt dataRateCfg = 0; |
|
133 TRAP( paramErr, dataRateCfg = iCfg->GetParameterIntL( KDataRate ) ); |
|
134 if ( paramErr != KErrNone ) |
|
135 { |
|
136 HTI_LOG_TEXT( "DataRate not defined in cfg, using default" ); |
|
137 } |
|
138 else |
|
139 { |
|
140 switch ( dataRateCfg ) |
|
141 { |
|
142 case 2400: |
|
143 iDataRate = EBps2400; |
|
144 break; |
|
145 case 4800: |
|
146 iDataRate = EBps4800; |
|
147 break; |
|
148 case 9600: |
|
149 iDataRate = EBps9600; |
|
150 break; |
|
151 case 19200: |
|
152 iDataRate = EBps19200; |
|
153 break; |
|
154 case 38400: |
|
155 iDataRate = EBps38400; |
|
156 break; |
|
157 case 57600: |
|
158 iDataRate = EBps57600; |
|
159 break; |
|
160 case 115200: |
|
161 iDataRate = EBps115200; |
|
162 break; |
|
163 case 576000: |
|
164 iDataRate = EBps576000; |
|
165 break; |
|
166 case 1152000: |
|
167 iDataRate = EBps1152000; |
|
168 break; |
|
169 case 4000000: |
|
170 iDataRate = EBps4000000; |
|
171 break; |
|
172 default: |
|
173 HTI_LOG_FORMAT( |
|
174 "Unsupported DataRate %d defined - using default", |
|
175 dataRateCfg ); |
|
176 break; |
|
177 } |
|
178 } |
|
179 |
|
180 TBuf8<64> parityCfg( KNullDesC8 ); |
|
181 TRAP( paramErr, parityCfg = iCfg->GetParameterL( KParity ) ); |
|
182 if ( paramErr != KErrNone || parityCfg.Length() == 0 ) |
|
183 { |
|
184 HTI_LOG_TEXT( "Parity not defined in cfg, using default" ); |
|
185 } |
|
186 else |
|
187 { |
|
188 if ( !parityCfg.CompareF( _L8( "none" ) ) ) |
|
189 { |
|
190 iParity = EParityNone; |
|
191 } |
|
192 else if ( !parityCfg.CompareF( _L8( "even" ) ) ) |
|
193 { |
|
194 iParity = EParityEven; |
|
195 } |
|
196 else if ( !parityCfg.CompareF( _L8( "odd" ) ) ) |
|
197 { |
|
198 iParity = EParityOdd; |
|
199 } |
|
200 else if ( !parityCfg.CompareF( _L8( "mark" ) ) ) |
|
201 { |
|
202 iParity = EParityMark; |
|
203 } |
|
204 else if ( !parityCfg.CompareF( _L8( "space" ) ) ) |
|
205 { |
|
206 iParity = EParitySpace; |
|
207 } |
|
208 else |
|
209 { |
|
210 HTI_LOG_TEXT( "Unsupported Parity defined - using default" ); |
|
211 } |
|
212 } |
|
213 |
|
214 TInt dataBitsCfg = 0; |
|
215 TRAP( paramErr, dataBitsCfg = iCfg->GetParameterIntL( KDataBits ) ); |
|
216 if ( paramErr != KErrNone ) |
|
217 { |
|
218 HTI_LOG_TEXT( "DataBits not defined in cfg, using default value" ); |
|
219 } |
|
220 else |
|
221 { |
|
222 switch ( dataBitsCfg ) |
|
223 { |
|
224 case 5: |
|
225 iDataBits = EData5; |
|
226 break; |
|
227 case 6: |
|
228 iDataBits = EData6; |
|
229 break; |
|
230 case 7: |
|
231 iDataBits = EData7; |
|
232 break; |
|
233 case 8: |
|
234 iDataBits = EData8; |
|
235 break; |
|
236 default: |
|
237 HTI_LOG_FORMAT( |
|
238 "Unsupported DataBits %d defined - using default", |
|
239 dataBitsCfg ); |
|
240 break; |
|
241 } |
|
242 } |
|
243 |
|
244 TInt stopBitsCfg = 0; |
|
245 TRAP( paramErr, stopBitsCfg = iCfg->GetParameterIntL( KStopBits ) ); |
|
246 if ( paramErr != KErrNone ) |
|
247 { |
|
248 HTI_LOG_TEXT( "StopBits not defined in cfg, using default value" ); |
|
249 } |
|
250 else |
|
251 { |
|
252 switch ( stopBitsCfg ) |
|
253 { |
|
254 case 1: |
|
255 iStopBits = EStop1; |
|
256 break; |
|
257 case 2: |
|
258 iStopBits = EStop2; |
|
259 break; |
|
260 default: |
|
261 HTI_LOG_FORMAT( |
|
262 "Unsupported StopBits %d defined - using default", |
|
263 stopBitsCfg ); |
|
264 break; |
|
265 } |
|
266 } |
|
267 |
|
268 TInt sendDelayCfg = 0; |
|
269 TRAP( paramErr, sendDelayCfg = iCfg->GetParameterIntL( KSendDelay ) ); |
|
270 if ( paramErr != KErrNone ) |
|
271 { |
|
272 HTI_LOG_TEXT( "SendDelay not defined in cfg, using default value" ); |
|
273 } |
|
274 else |
|
275 { |
|
276 iSendDelay = sendDelayCfg * 1000; // configured as milliseconds |
|
277 } |
|
278 |
|
279 TInt handshakeCfg = 0; |
|
280 TRAP( paramErr, handshakeCfg = iCfg->GetParameterIntL( KHandshake ) ); |
|
281 if ( paramErr != KErrNone ) |
|
282 { |
|
283 HTI_LOG_TEXT( |
|
284 "Handshake not defined in cfg, using default value" ); |
|
285 } |
|
286 else |
|
287 { |
|
288 iHandshake = handshakeCfg; |
|
289 } |
|
290 |
|
291 HTI_LOG_FUNC_OUT( "Serial::ReadConfig" ); |
|
292 } |
|
293 |
|
294 void CHtiSerialCommEcomPlugin::InitCommServerL() |
|
295 { |
|
296 HTI_LOG_FUNC_IN( "Serial::InitCommServerL" ); |
|
297 //load physical device driver |
|
298 TInt err = User::LoadPhysicalDevice( SERIAL_PDD_NAME ); |
|
299 if ( err != KErrNone && err != KErrAlreadyExists ) |
|
300 { |
|
301 ShowErrorNotifierL( _L( "Failed to load serial PDD" ), err ); |
|
302 User::Leave( err ); |
|
303 } |
|
304 |
|
305 //load logical device driver |
|
306 err = User::LoadLogicalDevice( SERIAL_LDD_NAME ); |
|
307 if ( err != KErrNone && err != KErrAlreadyExists ) |
|
308 { |
|
309 ShowErrorNotifierL( _L( "Failed to load serial LDD" ), err ); |
|
310 User::Leave( err ); |
|
311 } |
|
312 |
|
313 #if !defined (__WINS__) |
|
314 //User::After(1500000); //resolve |
|
315 //starts the comm server |
|
316 err = StartC32(); |
|
317 if ( err != KErrNone && err != KErrAlreadyExists ) |
|
318 User::Leave( err ); |
|
319 #endif |
|
320 |
|
321 //connect to RCommServ |
|
322 User::LeaveIfError( iCommServ.Connect() ); |
|
323 |
|
324 //load protocol module (CSY file) |
|
325 User::LeaveIfError( iCommServ.LoadCommModule( RS232_CSY_NAME ) ); |
|
326 HTI_LOG_FUNC_OUT( "Serial::InitCommServerL" ); |
|
327 } |
|
328 |
|
329 void CHtiSerialCommEcomPlugin::InitCommPortL() |
|
330 { |
|
331 HTI_LOG_FUNC_IN( "Serial::InitCommPortL" ); |
|
332 TInt numPorts; |
|
333 TInt err; |
|
334 err = iCommServ.NumPorts( numPorts ); |
|
335 User::LeaveIfError( err ); |
|
336 HTI_LOG_FORMAT( "NumPorts: %d", numPorts ); |
|
337 |
|
338 // we can get port information for each loaded CSY in turn (note we |
|
339 // index them from 0) - we can find out the number of ports supported |
|
340 // together with their names, and their description. The information is |
|
341 // returned in a TSerialInfo structure together with the name of the |
|
342 // CSY that we've indexed |
|
343 |
|
344 TSerialInfo portInfo; |
|
345 TBuf16<12> moduleName; |
|
346 |
|
347 for ( TInt index=0 ; index < numPorts ; index++ ) |
|
348 { |
|
349 err = iCommServ.GetPortInfo( index, moduleName, portInfo ); |
|
350 User::LeaveIfError( err ); |
|
351 HTI_LOG_FORMAT( "Port %d", index ); |
|
352 HTI_LOG_DES( moduleName ); |
|
353 HTI_LOG_DES( portInfo.iDescription ); |
|
354 HTI_LOG_DES( portInfo.iName ); |
|
355 HTI_LOG_FORMAT( "Low unit %d", portInfo.iLowUnit ); |
|
356 HTI_LOG_FORMAT( "High unit %d", portInfo.iHighUnit ); |
|
357 } |
|
358 |
|
359 TBuf<8> commPort; |
|
360 commPort.AppendFormat( _L( "COMM::%d" ), iPortNumber ); |
|
361 HTI_LOG_FORMAT( "Open serial port COMM::%d", iPortNumber ); |
|
362 err = iCommPort.Open( iCommServ, commPort, ECommExclusive ); |
|
363 if ( err ) |
|
364 { |
|
365 HTI_LOG_FORMAT( "Failed to open serial port %d", err ); |
|
366 ShowErrorNotifierL( _L( "Failed to open serial port" ), err ); |
|
367 } |
|
368 User::LeaveIfError( err ); |
|
369 |
|
370 // Just for debug purposes log the port capabilities |
|
371 TCommCaps portCapabilities; |
|
372 iCommPort.Caps( portCapabilities ); |
|
373 HTI_LOG_TEXT( "Port capabilities:" ); |
|
374 HTI_LOG_FORMAT( " DataRate = %d", portCapabilities().iRate ); |
|
375 HTI_LOG_FORMAT( " Parity = %d", portCapabilities().iParity ); |
|
376 HTI_LOG_FORMAT( " DataBits = %d", portCapabilities().iDataBits ); |
|
377 HTI_LOG_FORMAT( " StopBits = %d", portCapabilities().iStopBits ); |
|
378 HTI_LOG_FORMAT( " Handshake = %d", portCapabilities().iHandshake ); |
|
379 HTI_LOG_FORMAT( " Signals = %d", portCapabilities().iSignals ); |
|
380 HTI_LOG_FORMAT( " Fifo = %d", portCapabilities().iFifo ); |
|
381 HTI_LOG_FORMAT( " SIR = %d", portCapabilities().iSIR ); |
|
382 |
|
383 // Set port settings |
|
384 TCommConfig portSettings; |
|
385 iCommPort.Config( portSettings ); |
|
386 portSettings().iRate = iDataRate; |
|
387 portSettings().iParity = iParity; |
|
388 portSettings().iDataBits = iDataBits; |
|
389 portSettings().iStopBits = iStopBits; |
|
390 portSettings().iFifo = EFifoEnable; |
|
391 portSettings().iHandshake = iHandshake; |
|
392 |
|
393 HTI_LOG_TEXT( "Port settings enum values:" ); |
|
394 HTI_LOG_FORMAT( " DataRate %d", portSettings().iRate ); |
|
395 HTI_LOG_FORMAT( " Parity %d", portSettings().iParity ); |
|
396 HTI_LOG_FORMAT( " DataBits %d", portSettings().iDataBits ); |
|
397 HTI_LOG_FORMAT( " StopBits %d", portSettings().iStopBits ); |
|
398 HTI_LOG_FORMAT( " Handshake 0x%x", portSettings().iHandshake ); |
|
399 HTI_LOG_FORMAT( " Fifo %d", portSettings().iFifo ); |
|
400 |
|
401 // Now activate the settings |
|
402 err = iCommPort.SetConfig( portSettings ); |
|
403 if ( err ) |
|
404 { |
|
405 HTI_LOG_FORMAT( "failed to set port settings %d", err ); |
|
406 ShowErrorNotifierL( _L( "Failed to set port settings" ), err ); |
|
407 } |
|
408 User::LeaveIfError( err ); |
|
409 |
|
410 // Turn on DTR and RTS, and set our buffer size |
|
411 iCommPort.SetSignals( KSignalDTR, 0 ); |
|
412 iCommPort.SetSignals( KSignalRTS, 0 ); |
|
413 |
|
414 iCommPort.SetReceiveBufferLength( KReceiveBufferLength ); |
|
415 |
|
416 // A null read or write powers up the port |
|
417 TRequestStatus readStat; |
|
418 TBuf8<1> temp_buffer; |
|
419 iCommPort.Read( readStat, temp_buffer, 0 ); |
|
420 User::WaitForRequest( readStat ); |
|
421 err = readStat.Int(); |
|
422 if ( err ) |
|
423 { |
|
424 HTI_LOG_FORMAT( "Failed to power up the port %d", err ); |
|
425 ShowErrorNotifierL( _L( "Failed to power up the port" ), err ); |
|
426 } |
|
427 User::LeaveIfError( err ); |
|
428 |
|
429 HTI_LOG_FUNC_OUT( "Serial::InitCommPortL" ); |
|
430 } |
|
431 |
|
432 void CHtiSerialCommEcomPlugin::Receive( TDes8& aRawdataBuf, |
|
433 TRequestStatus& aStatus ) |
|
434 { |
|
435 HTI_LOG_FUNC_IN( "Serial::Receive" ); |
|
436 HTI_LOG_FORMAT( "Buf max len: %d", aRawdataBuf.MaxLength() ); |
|
437 iCommPort.ReadOneOrMore( aStatus, aRawdataBuf ); |
|
438 HTI_LOG_FUNC_OUT( "Serial::Receive" ); |
|
439 } |
|
440 |
|
441 void CHtiSerialCommEcomPlugin::Send( const TDesC8& aRawdataBuf, |
|
442 TRequestStatus& aStatus ) |
|
443 { |
|
444 HTI_LOG_FUNC_IN( "Serial::Send" ); |
|
445 iCommPort.Write( aStatus, aRawdataBuf ); |
|
446 if ( iSendDelay > 0 ) // optional wait - can be set in serial comm cfg |
|
447 { |
|
448 // If sending large amounts of data from Symbian to PC is failing, |
|
449 // the wait here seems to help. |
|
450 User::After( iSendDelay ); |
|
451 } |
|
452 HTI_LOG_FUNC_OUT( "Serial::Send" ); |
|
453 } |
|
454 |
|
455 void CHtiSerialCommEcomPlugin::CancelReceive() |
|
456 { |
|
457 HTI_LOG_FUNC_IN( "Serial::CancelReceive" ); |
|
458 iCommPort.ReadCancel(); |
|
459 HTI_LOG_FUNC_OUT( "Serial::CancelReceive" ); |
|
460 } |
|
461 |
|
462 void CHtiSerialCommEcomPlugin::CancelSend() |
|
463 { |
|
464 HTI_LOG_FUNC_IN( "Serial::CancelSend" ); |
|
465 iCommPort.WriteCancel(); |
|
466 HTI_LOG_FUNC_OUT( "Serial::CancelSend" ); |
|
467 } |
|
468 |
|
469 TInt CHtiSerialCommEcomPlugin::GetSendBufferSize() |
|
470 { |
|
471 return KSendBufferLength; |
|
472 } |
|
473 |
|
474 TInt CHtiSerialCommEcomPlugin::GetReceiveBufferSize() |
|
475 { |
|
476 return KReceiveBufferLength; |
|
477 } |
|
478 |
|
479 void CHtiSerialCommEcomPlugin::ShowErrorNotifierL( const TDesC& aText, |
|
480 TInt aErr ) |
|
481 { |
|
482 RNotifier notifier; |
|
483 User::LeaveIfError( notifier.Connect() ); |
|
484 |
|
485 TBuf<KMaxHtiNotifierLength> errorMsg; |
|
486 // aText is cut if it's too long - leaving some space also for error code |
|
487 errorMsg.Append( aText.Left( errorMsg.MaxLength() - 10 ) ); |
|
488 errorMsg.Append( _L("\n") ); |
|
489 errorMsg.AppendNum( aErr ); |
|
490 |
|
491 TRequestStatus status; |
|
492 TInt button; |
|
493 notifier.Notify( KHtiSerialError, errorMsg, |
|
494 KHtiOkButton, KNullDesC, button, status ); |
|
495 User::WaitForRequest( status ); |
|
496 notifier.Close(); |
|
497 } |
|