|
1 // Copyright (c) 1998-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\device\t_dtenot.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <e32base.h> |
|
19 #include <e32base_private.h> |
|
20 #include <e32test.h> |
|
21 #include <e32cons.h> |
|
22 #include <e32svr.h> |
|
23 #include <e32hal.h> |
|
24 #include <d32comm.h> |
|
25 #include <e32uid.h> |
|
26 #include <hal.h> |
|
27 |
|
28 const TInt KUnit0=0; |
|
29 const TInt KUnit1=1; |
|
30 const TInt KUnit2=2; |
|
31 const TInt KUnit3=3; |
|
32 |
|
33 #if defined (__WINS__) |
|
34 #define PDD_NAME _L("ECDRV.PDD") |
|
35 #define LDD_NAME _L("ECOMM.LDD") |
|
36 #else |
|
37 #define PDD_NAME _L("EUART") |
|
38 #define LDD_NAME _L("ECOMM") |
|
39 #endif |
|
40 |
|
41 #define CHECK(r,v) {if ((r)!=(v)) {test.Printf(_L("Line %d Expected %08x Got %08x\n"),__LINE__,(v),(r)); test(0);}} |
|
42 |
|
43 // Our own comms object with synchronous writes |
|
44 class RComm : public RBusDevComm |
|
45 { |
|
46 public: |
|
47 TInt WriteS(const TDesC8& aDes); |
|
48 TInt WriteS(const TDesC8& aDes,TInt aLength); |
|
49 }; |
|
50 |
|
51 LOCAL_D RTest test(_L("T_DTENOT")); |
|
52 |
|
53 RComm* theSerialPort; |
|
54 TCommCaps2 theCapsBuf; |
|
55 TCommCapsV02& theCaps=theCapsBuf(); |
|
56 |
|
57 TInt RComm::WriteS(const TDesC8& aDes) |
|
58 |
|
59 // Syncronous write |
|
60 |
|
61 { |
|
62 return(WriteS(aDes,aDes.Length())); |
|
63 } |
|
64 |
|
65 TInt RComm::WriteS(const TDesC8& aDes,TInt aLength) |
|
66 |
|
67 // Syncronous write |
|
68 |
|
69 { |
|
70 |
|
71 TRequestStatus s; |
|
72 Write(s,aDes,aLength); |
|
73 User::WaitForRequest(s); |
|
74 return(s.Int()); |
|
75 } |
|
76 |
|
77 enum TSetClearOutSignal {ESetOutSignal,EClearOutSignal}; |
|
78 enum TOutcomeExpected {EExpectNotify,EExpectTimeout}; |
|
79 enum TSigChngNotifyType {ENotifyOnInSigOnly,ENotifyOnAnyChange}; |
|
80 LOCAL_C void TestNotifySignalChange(TUint anOutSig,TSetClearOutSignal aSetClr,TUint anInSig,TOutcomeExpected anExpect,TSigChngNotifyType aType) |
|
81 // |
|
82 // Change the state of the specified output signal and wait up to 2 seconds for |
|
83 // this to trigger a change notification. |
|
84 // |
|
85 { |
|
86 RTimer tim; |
|
87 tim.CreateLocal(); |
|
88 TRequestStatus notifStatus; |
|
89 TRequestStatus timeStatus; |
|
90 |
|
91 TUint signals=0; |
|
92 if (aType==ENotifyOnAnyChange) |
|
93 theSerialPort->NotifySignalChange(notifStatus,signals); |
|
94 else |
|
95 theSerialPort->NotifySignalChange(notifStatus,signals,anInSig); |
|
96 // CHECK(notifStatus.Int(),KRequestPending); |
|
97 const TUint KTimeOut=2000000; |
|
98 tim.After(timeStatus,KTimeOut); |
|
99 CHECK(timeStatus.Int(),KRequestPending); |
|
100 if (aSetClr==ESetOutSignal) |
|
101 theSerialPort->SetSignals(anOutSig,0); // Set Out signal |
|
102 else |
|
103 theSerialPort->SetSignals(0,anOutSig); // Clear Out signal |
|
104 User::WaitForRequest(notifStatus,timeStatus); |
|
105 if (notifStatus!=KRequestPending) |
|
106 { |
|
107 test.Printf(_L("notifStatus=%08x\n"),notifStatus.Int()); |
|
108 tim.Cancel(); |
|
109 User::WaitForRequest(timeStatus); |
|
110 if (anExpect==EExpectNotify) |
|
111 { |
|
112 // Got a notification as expected - but was it the correct notification? |
|
113 TUint sigmask=(anInSig*KSignalChanged); |
|
114 if (aSetClr==ESetOutSignal) |
|
115 sigmask|=anInSig; |
|
116 if (aType==ENotifyOnAnyChange) |
|
117 {CHECK((signals&sigmask),sigmask);} |
|
118 else |
|
119 {CHECK(signals,sigmask);} |
|
120 } |
|
121 else |
|
122 { |
|
123 test.Printf(_L("Spurious notify %d %08x\n"),notifStatus.Int(),signals); |
|
124 test(FALSE); // Unexpectedly got notification |
|
125 } |
|
126 } |
|
127 else |
|
128 { |
|
129 test.Printf(_L("timeStatus=%08x\n"),timeStatus.Int()); |
|
130 theSerialPort->NotifySignalChangeCancel(); |
|
131 User::WaitForRequest(notifStatus); |
|
132 if (anExpect==EExpectNotify) |
|
133 { |
|
134 test.Printf(_L("Timed Out!\n\r")); |
|
135 test(FALSE); |
|
136 } |
|
137 else |
|
138 test(timeStatus==KErrNone); // Success |
|
139 } |
|
140 } |
|
141 |
|
142 GLDEF_C TInt E32Main() |
|
143 // |
|
144 // Test DTE serial driver change notification |
|
145 // |
|
146 { |
|
147 test.SetLogged(EFalse); // Turn off serial port debugging! |
|
148 |
|
149 test.Title(); |
|
150 test.Start(_L("Check loopback connector")); |
|
151 |
|
152 TBuf <0x100> cmd; |
|
153 User::CommandLine(cmd); |
|
154 TInt port=0; |
|
155 if ((cmd.Length()>0) && (cmd[0]>='0' && cmd[0]<='9')) |
|
156 port=(TInt)(cmd[0]-'0'); |
|
157 |
|
158 // Read machine name to determine handshake options required |
|
159 TInt mid; |
|
160 TInt r=HAL::Get(HAL::EMachineUid,mid); |
|
161 test(r==KErrNone); |
|
162 |
|
163 TUint handshake=(KConfigFreeRTS|KConfigFreeDTR); // So we can control them ourselves |
|
164 if (mid==HAL::EMachineUid_Brutus && port<3) |
|
165 handshake=0; // Brutus can't support these option on ports 0-2 |
|
166 |
|
167 test.Printf(_L("\r\nThis test requires a loopback conector.\r\n")); |
|
168 test.Printf(_L("<<Hit a key to continue>>\r\n")); |
|
169 test.Getch(); |
|
170 |
|
171 TInt muid=0; |
|
172 test(HAL::Get(HAL::EMachineUid, muid)==KErrNone); |
|
173 TBool isAssabet=(muid==HAL::EMachineUid_Assabet); |
|
174 |
|
175 // Load Device Drivers |
|
176 TBuf<10> pddName=PDD_NAME; |
|
177 test.Next(_L("Load PDDs")); |
|
178 #ifdef __WINS__ |
|
179 const TInt KMaxPdds=0; |
|
180 #else |
|
181 const TInt KMaxPdds=10; |
|
182 #endif |
|
183 TInt i; |
|
184 for (i=-1; i<KMaxPdds; ++i) |
|
185 { |
|
186 if (i==0) |
|
187 pddName.Append(TChar('0')); |
|
188 else if (i>0) |
|
189 pddName[pddName.Length()-1]=TText('0'+i); |
|
190 r=User::LoadPhysicalDevice(pddName); |
|
191 if (r==KErrNone || r==KErrAlreadyExists) |
|
192 test.Printf(_L("PDD %S loaded\n"),&pddName); |
|
193 } |
|
194 |
|
195 test.Next(_L("Load LDD")); |
|
196 r=User::LoadLogicalDevice(LDD_NAME); |
|
197 test.Printf(_L("Load LDD Return %d\n\r"),r); |
|
198 |
|
199 test.Next(_L("Create RComm object")); |
|
200 theSerialPort=new RComm; |
|
201 test(theSerialPort!=NULL); |
|
202 // |
|
203 test.Next(_L("Open:")); |
|
204 r=theSerialPort->Open(port); |
|
205 test.Printf(_L("Open(%d)=%d\n\r"),port,r); |
|
206 test(r==KErrNone); |
|
207 |
|
208 test.Next(_L("Get caps and configure port")); |
|
209 theSerialPort->Caps(theCapsBuf); |
|
210 CHECK(r,KErrNone); |
|
211 test.Printf(_L("Signals(DTR-RTS-RI-DCD-DSR-CTS) %x\n\r"),theCaps.iSignals); |
|
212 test.Printf(_L("Notifications %x\n\r"),theCaps.iNotificationCaps); |
|
213 |
|
214 TCommConfig cBuf; |
|
215 TCommConfigV01& c=cBuf(); |
|
216 theSerialPort->Config(cBuf); |
|
217 c.iHandshake=handshake; |
|
218 c.iDataBits=EData8; |
|
219 c.iStopBits=EStop1; |
|
220 c.iParity=EParityNone; |
|
221 c.iRate=EBps9600; |
|
222 r=theSerialPort->SetConfig(cBuf); |
|
223 CHECK(r,KErrNone); |
|
224 |
|
225 RTimer tim; |
|
226 tim.CreateLocal(); |
|
227 TRequestStatus notifStatus; |
|
228 TRequestStatus timeStatus; |
|
229 |
|
230 test.Next(_L("Testing NotifySignalChange()")); |
|
231 if (!(theCaps.iNotificationCaps & KNotifySignalsChangeSupported)) |
|
232 test.Printf(_L("WARNING - Signal change notification not supported on this platform\r\n")); |
|
233 else |
|
234 { |
|
235 if ((theCaps.iSignals&(KCapsSignalCTSSupported|KCapsSignalRTSSupported))!=(KCapsSignalCTSSupported|KCapsSignalRTSSupported)) |
|
236 test.Printf(_L("WARNING - RTS/CTS not supported on this platform\r\n")); |
|
237 else |
|
238 { |
|
239 #ifndef __WINS__ |
|
240 TUint signals=0xffffffff; |
|
241 theSerialPort->SetSignals(0,KSignalRTS); // Clear RTS |
|
242 User::After(100000); |
|
243 test.Next(_L("Initial notifier")); |
|
244 theSerialPort->NotifySignalChange(notifStatus,signals); |
|
245 User::WaitForRequest(notifStatus); |
|
246 test(notifStatus==KErrNone); // goes off immediately the first time |
|
247 test.Printf(_L("Signals %08x\n"),signals); |
|
248 test((signals&(KSignalRTS|KSignalCTS))==0); |
|
249 #endif |
|
250 // Test with no signal mask set |
|
251 |
|
252 isAssabet=0; |
|
253 if (isAssabet) |
|
254 { |
|
255 // test.Next(_L(" CTS(set) notify without mask set")); |
|
256 // TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalCTS,EExpectNotify,ENotifyOnAnyChange); |
|
257 // (CF) Note: This test presents some problems: we specify notification on any signal but the test only |
|
258 // passes if the input signal specified (CTS) has changed. The test code makes a request for |
|
259 // notification on any signal (iSignalMask=0x3f) and THEN changes an output signal (RTS) that's |
|
260 // wired to the input signal specified (CTS). But changing an output signal launches the DFC |
|
261 // to complete the notification request reporting a change on the output signal NOT the input |
|
262 // signal. The only reason most platforms pass this test is because, on them, input signal changes |
|
263 // trigger interrupts: due to the loopback between output and input signals, when the output |
|
264 // signal changes so does the input signal and that triggers an interrupt which also launches |
|
265 // a DFC to complete the notification request reporting a change on the input signal. |
|
266 // The interrupt is serviced before the output signal notification DFC is scheduled and |
|
267 // the notification request is completed with the input signal change. |
|
268 // On Assabet Modem control signals are polled instead of generating interrupts (Intel's design |
|
269 // flaw) and therefore the output signal change will complete the notification (in error) before |
|
270 // the input signal change is notified. |
|
271 // |
|
272 test.Next(_L(" RTS(set) notify without mask set")); |
|
273 TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalRTS,EExpectNotify,ENotifyOnAnyChange); |
|
274 test.Next(_L(" RTS(clear) notify without mask set")); |
|
275 TestNotifySignalChange(KSignalRTS,EClearOutSignal,KSignalRTS,EExpectNotify,ENotifyOnAnyChange); |
|
276 } |
|
277 else |
|
278 { |
|
279 test.Next(_L(" CTS(set) notify without mask set")); |
|
280 TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalCTS,EExpectNotify,ENotifyOnAnyChange); |
|
281 test.Next(_L(" CTS(clear) notify without mask set")); |
|
282 TestNotifySignalChange(KSignalRTS,EClearOutSignal,KSignalCTS,EExpectNotify,ENotifyOnAnyChange); |
|
283 } |
|
284 |
|
285 // Test notification doesn't happen with signal mask set to some other signal |
|
286 test.Next(_L(" No CTS(set) notify with mask set to other signal")); |
|
287 TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalDSR,EExpectTimeout,ENotifyOnInSigOnly); |
|
288 TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalCTS,EExpectNotify,ENotifyOnInSigOnly); |
|
289 |
|
290 // Test notification happens with mask set to this signal |
|
291 test.Next(_L(" CTS(clear) notify with mask set")); |
|
292 TestNotifySignalChange(KSignalRTS,EClearOutSignal,KSignalCTS,EExpectNotify,ENotifyOnInSigOnly); |
|
293 test.Next(_L(" CTS(set) notify with mask set")); |
|
294 TestNotifySignalChange(KSignalRTS,ESetOutSignal,KSignalCTS,EExpectNotify,ENotifyOnInSigOnly); |
|
295 } |
|
296 |
|
297 if ((theCaps.iSignals&(KCapsSignalDSRSupported|KCapsSignalDTRSupported))!=(KCapsSignalDSRSupported|KCapsSignalDTRSupported)) |
|
298 test.Printf(_L("WARNING - DTR/DSR not supported on this platform\r\n")); |
|
299 else |
|
300 { |
|
301 theSerialPort->SetSignals(0,KSignalDTR); // Clear DTR |
|
302 User::After(100000); |
|
303 |
|
304 // Test with no signal mask set |
|
305 |
|
306 if (isAssabet) |
|
307 { |
|
308 // (CF) See note above |
|
309 test.Next(_L(" DTR(set) notify without mask set")); |
|
310 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDTR,EExpectNotify,ENotifyOnAnyChange); |
|
311 test.Next(_L(" DTR(clear) notify without mask set")); |
|
312 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDTR,EExpectNotify,ENotifyOnAnyChange); |
|
313 } |
|
314 else |
|
315 { |
|
316 test.Next(_L(" DSR(set) notify without mask set")); |
|
317 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDSR,EExpectNotify,ENotifyOnAnyChange); |
|
318 test.Next(_L(" DSR(clear) notify without mask set")); |
|
319 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDSR,EExpectNotify,ENotifyOnAnyChange); |
|
320 } |
|
321 |
|
322 // Test notification happens with mask set to this signal |
|
323 test.Next(_L(" DSR(set) notify with mask set")); |
|
324 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDSR,EExpectNotify,ENotifyOnInSigOnly); |
|
325 test.Next(_L(" DSR(clear) notify with mask set")); |
|
326 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDSR,EExpectNotify,ENotifyOnInSigOnly); |
|
327 } |
|
328 |
|
329 if (mid==HAL::EMachineUid_Series5mx || |
|
330 (theCaps.iSignals&(KCapsSignalDCDSupported|KCapsSignalDTRSupported))!=(KCapsSignalDCDSupported|KCapsSignalDTRSupported)) |
|
331 test.Printf(_L("WARNING - DTR/DCD not supported on this platform\r\n")); |
|
332 else |
|
333 { |
|
334 // Test with no signal mask set |
|
335 |
|
336 if (isAssabet) |
|
337 { |
|
338 // (CF) See note above |
|
339 test.Next(_L(" DTR(set) notify without mask set")); |
|
340 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDTR,EExpectNotify,ENotifyOnAnyChange); |
|
341 test.Next(_L(" DTR(clear) notify without mask set")); |
|
342 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDTR,EExpectNotify,ENotifyOnAnyChange); |
|
343 } |
|
344 else |
|
345 { |
|
346 test.Next(_L(" DCD(set) notify without mask set")); |
|
347 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDCD,EExpectNotify,ENotifyOnAnyChange); |
|
348 test.Next(_L(" DCD(clear) notify without mask set")); |
|
349 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDCD,EExpectNotify,ENotifyOnAnyChange); |
|
350 } |
|
351 |
|
352 |
|
353 // Test notification happens with mask set to this signal |
|
354 test.Next(_L(" DCD(set) notify with mask set")); |
|
355 TestNotifySignalChange(KSignalDTR,ESetOutSignal,KSignalDCD,EExpectNotify,ENotifyOnInSigOnly); |
|
356 test.Next(_L(" DCD(clear) notify with mask set")); |
|
357 TestNotifySignalChange(KSignalDTR,EClearOutSignal,KSignalDCD,EExpectNotify,ENotifyOnInSigOnly); |
|
358 } |
|
359 } |
|
360 |
|
361 test.Next(_L("Testing NotifyReceiveDataAvailable()")); |
|
362 if (!(theCaps.iNotificationCaps & KNotifyDataAvailableSupported)) |
|
363 test.Printf(_L("Data available notification not supported on this platform\r\n")); |
|
364 else |
|
365 { |
|
366 TBuf8<0x10> buf1(0x10), buf2(0x10); |
|
367 for (TInt i=0;i<0x10;i++) buf1[i]=(TUint8)i; |
|
368 |
|
369 theSerialPort->ResetBuffers(); |
|
370 theSerialPort->NotifyReceiveDataAvailable(notifStatus); |
|
371 CHECK(notifStatus.Int(),KRequestPending); |
|
372 const TUint KTimeOut=2000000; |
|
373 tim.After(timeStatus,KTimeOut); |
|
374 CHECK(timeStatus.Int(),KRequestPending); |
|
375 theSerialPort->WriteS(buf1); |
|
376 User::WaitForRequest(notifStatus,timeStatus); |
|
377 if (notifStatus==KErrNone) |
|
378 { |
|
379 tim.Cancel(); |
|
380 CHECK(notifStatus.Int(),KErrNone); |
|
381 } |
|
382 else |
|
383 { |
|
384 test.Printf(_L("Timed Out!\n\r")); |
|
385 theSerialPort->NotifyReceiveDataAvailableCancel(); |
|
386 test(FALSE); |
|
387 } |
|
388 User::After(500000); |
|
389 CHECK(theSerialPort->QueryReceiveBuffer(),0x10); |
|
390 buf2.FillZ(); |
|
391 theSerialPort->Read(notifStatus,buf2,0x10); |
|
392 User::WaitForRequest(notifStatus); |
|
393 test(buf1.Compare(buf2)==0); |
|
394 } |
|
395 |
|
396 theSerialPort->Close(); |
|
397 test.Printf(_L("<<Hit a key to end>>\r\n")); |
|
398 test.Getch(); |
|
399 test.End(); |
|
400 return(KErrNone); |
|
401 } |
|
402 |
|
403 |