|
1 // Copyright (c) 2007-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 "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 // This file implements the DExUartPhysicalChannelEmul class functions. |
|
15 // This is the implementation os serila port driver for emulator |
|
16 // target, i.e serial port of windows PC. This pdd is actually an |
|
17 // application for windows serial driver and therefore uses windows |
|
18 // API to access windows serial driver functionality |
|
19 // |
|
20 // |
|
21 |
|
22 // include h4 specific header file |
|
23 #include "d_expio_emul.h" |
|
24 |
|
25 /** |
|
26 PDD entry point |
|
27 This function is called when the PDD is loaded. This creates a factory |
|
28 object for PDD. DECLARE_STANDARD_PDD macro defines the first export to |
|
29 represent the DLL factory function, that will be called first by loader |
|
30 after loading the PDD. |
|
31 */ |
|
32 DECLARE_STANDARD_PDD() |
|
33 { |
|
34 // Create a PDD factory object, i.e instance of DPhysicalDevice derived |
|
35 // class. This is the first step that is done after loading the driver. |
|
36 // Physical device constructor inturn creates a Physical Channel. |
|
37 // |
|
38 DExEmulPhysicalDevice* pD = new DExEmulPhysicalDevice; |
|
39 if(pD) |
|
40 { |
|
41 // TDynamicDfcQue is used for creating and destroying a DFC as needed |
|
42 // This extends TDfcQue with destroy method. This ensures there is |
|
43 // no memory leak done while using DFC queue |
|
44 // |
|
45 TDynamicDfcQue* pDfcQ; |
|
46 // Create a new DFC queue using kernel API, Kern::DynamicDfcQCreate(). It |
|
47 // allocates a TDynamicDfcQue object on the heap and initializes it with |
|
48 // provided parameters like thread priority for the queue. Thread priority |
|
49 // has to be chosen carefully, as priority higher than the kernel threads |
|
50 // used for timers may adversely effect the system performance, nano |
|
51 // kernel ticks. |
|
52 // |
|
53 TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExEmulUartDfcPriority, |
|
54 KExEmulUartDfcName); |
|
55 if (KErrNone==r) |
|
56 { |
|
57 // Store the DFC thread pointer to return when required |
|
58 pD->iDfcQueue = pDfcQ; |
|
59 // Success return point |
|
60 return pD; |
|
61 } |
|
62 // if DFCQ creation failed, then fail the PDD loading, hence asynchronously close |
|
63 // the LDD factory object created. |
|
64 // |
|
65 pD->AsyncClose(); |
|
66 } |
|
67 // Failure exit point |
|
68 return NULL; |
|
69 } |
|
70 |
|
71 /** |
|
72 PDD factory constructor. This is called while creating the PDD factory |
|
73 object as a part of the driver (PDD) loading. This is called after the |
|
74 base class constructor, i.e DExUartPhysicalDevice() |
|
75 */ |
|
76 DExEmulPhysicalDevice::DExEmulPhysicalDevice() |
|
77 { |
|
78 // if multiple units are supported, then iUnitsMask is set here |
|
79 // to indicate the units being supported by the driver. |
|
80 } |
|
81 |
|
82 /** |
|
83 Physical device destructor. This is called whicle unloading the PDD |
|
84 */ |
|
85 DExEmulPhysicalDevice::~DExEmulPhysicalDevice() |
|
86 { |
|
87 // If a Dynamic Dfc Queue is created, delete it to ensure there is no |
|
88 // memory leak. |
|
89 // |
|
90 if (iDfcQueue) |
|
91 { |
|
92 // Destroys the DFC queue.The function destroys the DFC queue, killing |
|
93 // the DFC thread and deleting the TDynamicDfcQue object itself |
|
94 // |
|
95 iDfcQueue->Destroy(); |
|
96 } |
|
97 } |
|
98 |
|
99 /** |
|
100 PDD factory object (physical device) create. This is called by framework |
|
101 to create a physical channel. It is called in the context of the client |
|
102 user-side thread that requested the creation of the logical channel. |
|
103 This is a result of a user-side call to RBusLogicalChannel::DoCreate(). |
|
104 |
|
105 @param aChannel |
|
106 reference to the physical channel object created |
|
107 |
|
108 @return KErrNone for success or KErrNoMemory for failure |
|
109 */ |
|
110 TInt DExEmulPhysicalDevice::Create(DBase*& aChannel,TInt aUnit, const TDesC8* aInfo, |
|
111 const TVersion& aVer) |
|
112 { |
|
113 // Create the Physical channel |
|
114 DExUartPhysicalChannelEmul *device = new DExUartPhysicalChannelEmul; |
|
115 if (!device) |
|
116 return KErrNoMemory; |
|
117 |
|
118 aChannel = device; |
|
119 |
|
120 // Call the second stage contructor of physical channel |
|
121 return device->DoCreate(aUnit,aInfo,aVer); |
|
122 } |
|
123 |
|
124 /** |
|
125 Constructor for physical channel. Called after the base class constructor |
|
126 */ |
|
127 DExUartPhysicalChannelEmul::DExUartPhysicalChannelEmul() |
|
128 :iConfigured(EFalse), |
|
129 iBytesRead(0), |
|
130 iRxPollTimer(RxPollTimerCallback,this) // Timer to poll Rx data |
|
131 { |
|
132 } |
|
133 |
|
134 /** |
|
135 Hardware peripheral class (uart) Destructor |
|
136 */ |
|
137 DExUartPhysicalChannelEmul::~DExUartPhysicalChannelEmul() |
|
138 { |
|
139 // Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel |
|
140 // timer. Removes this timer from the nanokernel timer queue. |
|
141 // Does nothing if the timer is inactive or has already expired. |
|
142 // If the timer was queued and DFC callback requested it is possible |
|
143 // for the expiry handler to run even after Cancel() has been called. |
|
144 // |
|
145 if (iTimerStatus==KTimerStarted) |
|
146 iRxPollTimer.Cancel(); |
|
147 |
|
148 // close the port if the handle is invalid |
|
149 if (hCommPort!=INVALID_HANDLE_VALUE) |
|
150 { |
|
151 // Close the Serial Port after reading data |
|
152 CloseHandle(hCommPort); |
|
153 KEXDEBUG(Kern::Printf("Emulator::Serial Port Closed")); |
|
154 } |
|
155 } |
|
156 |
|
157 /** |
|
158 Physical channel second stage constructor. This is called from the DPhysicalDevice::Create() |
|
159 after creating the physical channel. Any further initializations as a part of the physical |
|
160 channel creation are done here. |
|
161 |
|
162 @param aUnit |
|
163 device unit number |
|
164 @param aInfo |
|
165 device related information |
|
166 @param aVer |
|
167 version number |
|
168 @return |
|
169 */ |
|
170 TInt DExUartPhysicalChannelEmul::DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer) |
|
171 { |
|
172 TInt r; |
|
173 |
|
174 // We are not using these parameters here, and therefore making them void to avoid any |
|
175 // warning messages during build. If multiple units are supported, creating the channel |
|
176 // w.r.t unit can be controlled here |
|
177 // |
|
178 (void)aUnit; |
|
179 (void)aInfo; |
|
180 (void)aVer; |
|
181 |
|
182 // TCommConfigV01 structure defined in d32comm.h is used |
|
183 // to hold the configuration details like baudrate, parity, |
|
184 // databits etc for serial |
|
185 // |
|
186 TCommConfigV01 cfg; |
|
187 // Configure the channel by default, (9600 baud rate) |
|
188 cfg.iRate = EBps9600; |
|
189 r = Configure(cfg); |
|
190 if (r!=KErrNone) |
|
191 { |
|
192 // Configuration failed, still continue by updating device state |
|
193 iConfigured=EFalse; |
|
194 } |
|
195 else |
|
196 { |
|
197 // Device configured successfully |
|
198 iConfigured=ETrue; |
|
199 } |
|
200 |
|
201 // Physical channel creation is successful |
|
202 return KErrNone; |
|
203 } |
|
204 |
|
205 /** |
|
206 DfcQ - Creates a DFC queue dedicated for the tutorial driver. By default |
|
207 logical channel derived from DLogicalChannel has a DFCQ, and DFC thread 0 |
|
208 is generally used. However, driver can choose o create it's own DFC and |
|
209 use it for queuing it's messages to this queue. In this case, PDD can |
|
210 implement this function, DfcQ(), which is called by LDD to initialize it's |
|
211 messgage queue with this DFC. |
|
212 |
|
213 @return refernce to the created TDynamicDfcQue object |
|
214 */ |
|
215 TDynamicDfcQue* DExUartPhysicalChannelEmul::DfcQ() |
|
216 { |
|
217 // return the dfc thread created for this driver. one per uint/device |
|
218 return ((DExEmulPhysicalDevice*)iLdd->iPhysicalDevice)->iDfcQueue; |
|
219 } |
|
220 |
|
221 /** |
|
222 Get the capabilities of the channel. This can be used by the user to get |
|
223 the capabilities for the channel from PSL. |
|
224 |
|
225 @param aCaps |
|
226 descriptor returned after filling with capabilities |
|
227 */ |
|
228 void DExUartPhysicalChannelEmul:: Caps(TDes8& aCaps) |
|
229 { |
|
230 // Package buffer of TCommCapsV03. This creates a descriptor |
|
231 // for the commcaps structure, and provide compatibility |
|
232 // to use with API using descriptors |
|
233 // |
|
234 TCommCaps3 capsBuf; |
|
235 |
|
236 // Retrieves the data structure from the package buffer. TCommCapsV03 |
|
237 // holds the uart capabilities information. |
|
238 // |
|
239 TCommCapsV03 &caps=capsBuf(); |
|
240 |
|
241 caps.iRate=KCapsBps9600; // baudrate |
|
242 caps.iDataBits=KCapsData8; // data size |
|
243 caps.iFifo=KCapsHasFifo; // fifo enabled |
|
244 caps.iBreakSupported=EFalse;// no braek support |
|
245 |
|
246 // [TDes8::MaxLength()] - Get the descriptor's length. |
|
247 TInt len = aCaps.MaxLength(); |
|
248 |
|
249 // [TDes8::FillZ(len)] -Fill the descriptor's data area with binary |
|
250 // zeroes, replacing any existing data and change its length. |
|
251 aCaps.FillZ(len); |
|
252 |
|
253 TInt size = sizeof(caps); |
|
254 if (size>len) |
|
255 size=len; |
|
256 |
|
257 // [TDes8::Copy()] - Copy the data of length (size) into aDes descriptor |
|
258 // replacing any existing data in the descriptor. |
|
259 aCaps.Copy((TUint8*)&caps, size); |
|
260 |
|
261 aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength())); |
|
262 } |
|
263 |
|
264 /** |
|
265 Configure the hardware device (Uart). This is device specific API, that |
|
266 provides functionality to configure the uart. Uart configuration settings are |
|
267 passed to this function by user. User calls this by using |
|
268 RBusLogicalChannel::DoControl() to LDD and ldd inturn calls this PDD function |
|
269 to do the actual operation on the device. |
|
270 |
|
271 @param aConfig |
|
272 configuration settings for the device |
|
273 |
|
274 @return KErrNone or standard error code |
|
275 */ |
|
276 TInt DExUartPhysicalChannelEmul::Configure(const TCommConfigV01& aConfig) |
|
277 { |
|
278 |
|
279 // if channel is already configured to same baud rate, then no need to |
|
280 // repeat the configuration |
|
281 // |
|
282 if (iConfigured!=EFalse) |
|
283 { |
|
284 if(iBaudRate==aConfig.iRate) |
|
285 return KErrNone; |
|
286 } |
|
287 |
|
288 iBaudRate = aConfig.iRate; |
|
289 |
|
290 // variables used with the com port |
|
291 BOOL bPortReady; |
|
292 DCB dcb; |
|
293 COMMTIMEOUTS commTimeouts; |
|
294 |
|
295 bPortReady = TRUE; // everything is OK so far |
|
296 |
|
297 // Open a serial port device using the CreateFile() function by specifying |
|
298 // a filename that refers to the specific port, such as COM1 or COM2. |
|
299 // |
|
300 // When you open a serial port, it is opened automatically for exclusive access, |
|
301 // so you should pass a zero for the CreateFile()'s third parameter and OPEN_EXISTING |
|
302 // for the open mode (fifth parameter). You can add a combination of the special file |
|
303 // mode flags to indicate overlapped I/O or any special buffering requirements, as normal. |
|
304 // |
|
305 // If the serial port opens successfully, a Win32 file object handle is returned. |
|
306 // Otherwise, INVALID_HANDLE_VALUE is returned. |
|
307 // |
|
308 hCommPort=CreateFileA((LPCSTR)"\\\\.\\com1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); |
|
309 |
|
310 if (hCommPort==INVALID_HANDLE_VALUE) |
|
311 { |
|
312 Kern::Printf("Emulator::Configure: FAILED"); |
|
313 |
|
314 bPortReady = FALSE; |
|
315 |
|
316 DWORD winErr=GetLastError(); |
|
317 switch (winErr) |
|
318 { |
|
319 case ERROR_INVALID_USER_BUFFER: |
|
320 case ERROR_NOT_ENOUGH_MEMORY: |
|
321 case ERROR_INSUFFICIENT_BUFFER: |
|
322 return(KErrNoMemory); |
|
323 case ERROR_ACCESS_DENIED: |
|
324 return(KErrAccessDenied); |
|
325 case ERROR_FILE_NOT_FOUND: // Reflects value returned by |
|
326 return(KErrNotSupported); // corresponding MARM Pdd |
|
327 case ERROR_NOT_SUPPORTED: |
|
328 return(KErrNotSupported); |
|
329 default: |
|
330 return(KErrGeneral); |
|
331 } |
|
332 } |
|
333 |
|
334 if (bPortReady) |
|
335 { |
|
336 bPortReady = SetupComm(hCommPort, 256, 256); // set buffer sizes |
|
337 if (!bPortReady) |
|
338 { |
|
339 return(KErrNoMemory); |
|
340 } |
|
341 } |
|
342 |
|
343 |
|
344 // After you open a serial port, you must set the many flags required to configure |
|
345 // the device. These flags are held in a device control block (DCB) structure. |
|
346 // You can either fill in the entire DCB structure or use one of the helper functions |
|
347 // to fill in some of the details. The GetCommState() function fills in a DCB structure |
|
348 // with the current settings from the hardware, and you can use a corresponding |
|
349 // SetCommState() function to specify the new settings from a DCB structure. |
|
350 // |
|
351 if (bPortReady) |
|
352 { |
|
353 bPortReady = GetCommState(hCommPort, &dcb); |
|
354 if (!bPortReady) |
|
355 { |
|
356 return(KErrGeneral); |
|
357 } |
|
358 } |
|
359 |
|
360 if (bPortReady) |
|
361 { |
|
362 //baud rate |
|
363 switch (aConfig.iRate) |
|
364 { |
|
365 case EBps9600: |
|
366 dcb.BaudRate=9600; |
|
367 break; |
|
368 case EBps38400: |
|
369 dcb.BaudRate=38400; |
|
370 break; |
|
371 case EBps115200: |
|
372 dcb.BaudRate=115200; |
|
373 break; |
|
374 default: |
|
375 dcb.BaudRate=9600; |
|
376 break; |
|
377 } |
|
378 |
|
379 //data bits |
|
380 switch(aConfig.iDataBits) |
|
381 { |
|
382 case EData7: |
|
383 dcb.ByteSize=7; |
|
384 break; |
|
385 case EData8: |
|
386 dcb.ByteSize=8; |
|
387 break; |
|
388 default: |
|
389 dcb.ByteSize=8; |
|
390 break; |
|
391 } |
|
392 |
|
393 //stop bits |
|
394 switch(aConfig.iStopBits) |
|
395 { |
|
396 case EStop1: |
|
397 dcb.StopBits=ONESTOPBIT; |
|
398 break; |
|
399 case EStop2: |
|
400 dcb.StopBits=TWOSTOPBITS; |
|
401 break; |
|
402 default: |
|
403 dcb.StopBits = ONESTOPBIT; |
|
404 break; |
|
405 } |
|
406 |
|
407 dcb.Parity = NOPARITY; |
|
408 |
|
409 bPortReady = SetCommState(hCommPort, &dcb); |
|
410 if (!bPortReady) |
|
411 { |
|
412 return(KErrGeneral); |
|
413 } |
|
414 } |
|
415 |
|
416 if (bPortReady) |
|
417 { |
|
418 // You can find the current timeout settings using the GetCommTimeout() |
|
419 // function, which fills a passed COMMTIMEOUTS structure. |
|
420 // |
|
421 bPortReady = GetCommTimeouts (hCommPort, &commTimeouts); |
|
422 if (bPortReady) |
|
423 { |
|
424 // You can set ReadIntervalTimeout to MAXDWORD and set the |
|
425 // ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant members |
|
426 // to zero to indicate that the ReadFile() should return immediately. |
|
427 // |
|
428 commTimeouts.ReadIntervalTimeout = MAXDWORD; |
|
429 commTimeouts.ReadTotalTimeoutConstant = 0; |
|
430 commTimeouts.ReadTotalTimeoutMultiplier = 0; |
|
431 } |
|
432 else |
|
433 { |
|
434 return(KErrGeneral); |
|
435 } |
|
436 if(!SetCommTimeouts(hCommPort, &commTimeouts)) |
|
437 return(KErrGeneral); |
|
438 |
|
439 } |
|
440 return KErrNone; |
|
441 } |
|
442 |
|
443 // After configuring the serial port, you can start transferring data via ReadFile() |
|
444 // and WriteFile() functions. However, you should remember that if you haven't specified |
|
445 // the FILE_FLAG_OVERLAPPED flag in the CreateFile() flags parameter, |
|
446 // ReadFile() will block waiting for input. This probably is good if your program spawns |
|
447 // another thread that specifically waits for incoming serial port characters, but not |
|
448 // if you want to issue a ReadFile() and periodically check to see whether any characters |
|
449 // have arrived. |
|
450 // |
|
451 |
|
452 /** |
|
453 Transmit data over uart for emulator targte, i.e serial port for pc |
|
454 Transmit data buffer is filled and passed by user to the driver |
|
455 |
|
456 @param aData |
|
457 buffer for transmit data |
|
458 |
|
459 @return KErrNone or standard error code |
|
460 */ |
|
461 TInt DExUartPhysicalChannelEmul::TransmitData(const TDesC8& aData) |
|
462 { |
|
463 TInt r; |
|
464 TInt count; |
|
465 TInt size; |
|
466 TInt offset=0; |
|
467 |
|
468 // if the device is not configured, try to configure the device again |
|
469 if (iConfigured==EFalse) |
|
470 { |
|
471 // Configure the channel by default |
|
472 TCommConfigV01 cfg; |
|
473 cfg.iRate = EBps9600; // 9600 baudrate |
|
474 r = Configure(cfg); |
|
475 if (r!=KErrNone) |
|
476 { |
|
477 // configure failed again, abort the request |
|
478 iConfigured=EFalse; |
|
479 return KErrAbort; |
|
480 } |
|
481 // configured successfully, continue with Tx |
|
482 iConfigured=ETrue; |
|
483 } |
|
484 |
|
485 // Size of the data to be transmitted is obtained from the descriptor. |
|
486 // TDesC8::Size() gets the size of the data interms of number of bytes occupied |
|
487 // by the data represented by the descriptor |
|
488 // |
|
489 count= aData.Size(); |
|
490 if (count<=0) |
|
491 return KErrAbort; |
|
492 |
|
493 // Loop till all the data sent from LDD is transmitted in blocks of KTxFifoSize |
|
494 while (count>0) |
|
495 { |
|
496 // Each block size can be max KTxFifoSize or less |
|
497 size=(count<KTxFifoSize)?count:KTxFifoSize; |
|
498 |
|
499 BOOL bWriteRC; |
|
500 DWORD iBytesWritten; |
|
501 |
|
502 iBytesWritten = 0; |
|
503 bWriteRC = WriteFile(hCommPort, aData.Ptr(), size, &iBytesWritten, NULL); |
|
504 |
|
505 if (!bWriteRC || iBytesWritten == 0) |
|
506 { |
|
507 return(KErrGeneral); |
|
508 } |
|
509 |
|
510 // calculate the offset |
|
511 offset+=iBytesWritten; |
|
512 // calculate the remaining buffer size |
|
513 count-=iBytesWritten; |
|
514 } |
|
515 |
|
516 return KErrNone; |
|
517 } |
|
518 |
|
519 /** |
|
520 Receive data over uart for emulator target, i.e uart of pc |
|
521 Receive data buffer is filled and passed by driver to the user |
|
522 |
|
523 @param aData |
|
524 buffer for received data |
|
525 |
|
526 @return KErrNone or standard error code |
|
527 */ |
|
528 TInt DExUartPhysicalChannelEmul::ReceiveData(TDes8& aData,TInt aLen) |
|
529 { |
|
530 TInt ret; |
|
531 TInt size; |
|
532 TInt count; |
|
533 TInt bytesRcvd=0; |
|
534 |
|
535 // Size of the data to be transmitted is obtained from the descriptor. |
|
536 // TDesC8::Size() gets the size of the data interms of number of bytes occupied |
|
537 // by the data represented by the descriptor |
|
538 // |
|
539 size= aLen; |
|
540 if (size<=0) |
|
541 return KErrAbort; // Zero length request, exit and fail |
|
542 |
|
543 // Keep track of the requested size |
|
544 count=size; |
|
545 |
|
546 // Loop till the requested amount of data from LDD is filled or a timeout |
|
547 while (count>0) |
|
548 { |
|
549 BOOL bReadRC; |
|
550 char sBuffer[256]; |
|
551 |
|
552 memset(sBuffer,0,sizeof(sBuffer)); |
|
553 // if no data and timer expired |
|
554 while ((bReadRC=ReadFile(hCommPort, sBuffer, sizeof(sBuffer), &iBytesRead, NULL)) == 0 |
|
555 || (iBytesRead==0)) |
|
556 { |
|
557 if (iTimerStatus==KTimerExpired) |
|
558 { |
|
559 aData.SetLength(bytesRcvd); |
|
560 return KErrTimedOut; |
|
561 } |
|
562 } |
|
563 |
|
564 if (iTimerStatus==KTimerStarted) |
|
565 { |
|
566 // Cancel the Rx poll timer. NTimer.Cancel() Cancel a nanokernel |
|
567 // timer. Removes this timer from the nanokernel timer queue. |
|
568 // Does nothing if the timer is inactive or has already expired. |
|
569 // If the timer was queued and DFC callback requested it is possible |
|
570 // for the expiry handler to run even after Cancel() has been called. |
|
571 // |
|
572 iRxPollTimer.Cancel(); |
|
573 // Update status as Cancelled |
|
574 iTimerStatus=KTimerCancelled; |
|
575 } |
|
576 |
|
577 if (bReadRC && (iBytesRead>0)) |
|
578 { |
|
579 if (iBytesRead>=static_cast<TUint>(size)) |
|
580 iBytesRead=size; |
|
581 aData.Append(TPtrC8((const TText8*)sBuffer,iBytesRead)); |
|
582 bytesRcvd+=iBytesRead; |
|
583 iBytesRead=0; |
|
584 } |
|
585 else |
|
586 { |
|
587 iTimerStatus = KTimerStarted; |
|
588 // Start a nanokernel timer in one-shot mode with ISR callback |
|
589 // Queues the timer to expire in the specified number of nanokernel |
|
590 // ticks. The actual wait time will be at least that much and |
|
591 // may be up to one tick more. The expiry handler will be called in |
|
592 // ISR context. |
|
593 // |
|
594 ret=iRxPollTimer.OneShot(KRxPollTimeout); |
|
595 if(ret!=KErrNone) // timer creation failed |
|
596 return ret; |
|
597 } |
|
598 |
|
599 // If we have received the requested number of bytes, return |
|
600 if (bytesRcvd>=size) |
|
601 { |
|
602 if (iTimerStatus == KTimerStarted) |
|
603 iRxPollTimer.Cancel(); |
|
604 return KErrNone; |
|
605 } |
|
606 |
|
607 // remaining bytes to be received |
|
608 count -= bytesRcvd; |
|
609 } |
|
610 |
|
611 return KErrNone; |
|
612 } |
|
613 |
|
614 void DExUartPhysicalChannelEmul::RxPollTimerCallback(TAny* aPtr) |
|
615 { |
|
616 KEXDEBUG(Kern::Printf("EMUL UART::Rx Timer Expired, Data Flow Stopped")); |
|
617 ((DExUartPhysicalChannelEmul*)aPtr)->iTimerStatus=KTimerExpired; |
|
618 } |
|
619 |
|
620 // |
|
621 // End of d_expio_emul.cpp |