VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/utils/serial/SerialTest.cpp@ 70693

Last change on this file since 70693 was 70652, checked in by vboxsync, 7 years ago

scm: fix spacing of a flowerbox comment

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.0 KB
Line 
1/* $Id: SerialTest.cpp 70652 2018-01-19 16:07:36Z vboxsync $ */
2/** @file
3 * SerialTest - Serial port testing utility.
4 */
5
6/*
7 * Copyright (C) 2017-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/err.h>
32#include <iprt/getopt.h>
33#include <iprt/mem.h>
34#include <iprt/path.h>
35#include <iprt/param.h>
36#include <iprt/process.h>
37#include <iprt/serialport.h>
38#include <iprt/stream.h>
39#include <iprt/string.h>
40#include <iprt/test.h>
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46
47
48
49/*********************************************************************************************************************************
50* Structures and Typedefs *
51*********************************************************************************************************************************/
52
53/** Pointer to the serial test data instance. */
54typedef struct SERIALTEST *PSERIALTEST;
55
56/**
57 * Test callback function.
58 *
59 * @returns IPRT status code.
60 * @param pSerialTest The serial test instance data.
61 */
62typedef DECLCALLBACK(int) FNSERIALTESTRUN(PSERIALTEST pSerialTest);
63/** Pointer to the serial test callback. */
64typedef FNSERIALTESTRUN *PFNSERIALTESTRUN;
65
66
67/**
68 * The serial test instance data.
69 */
70typedef struct SERIALTEST
71{
72 /** The assigned test handle. */
73 RTTEST hTest;
74 /** The assigned serial port. */
75 RTSERIALPORT hSerialPort;
76 /** The currently active config. */
77 PCRTSERIALPORTCFG pSerialCfg;
78} SERIALTEST;
79
80
81/**
82 * Test descriptor.
83 */
84typedef struct SERIALTESTDESC
85{
86 /** Test ID. */
87 const char *pszId;
88 /** Test description. */
89 const char *pszDesc;
90 /** Test run callback. */
91 PFNSERIALTESTRUN pfnRun;
92} SERIALTESTDESC;
93/** Pointer to a test descriptor. */
94typedef SERIALTESTDESC *PSERIALTESTDESC;
95/** Pointer to a constant test descriptor. */
96typedef const SERIALTESTDESC *PCSERIALTESTDESC;
97
98
99/**
100 * TX/RX buffer containing a simple counter.
101 */
102typedef struct SERIALTESTTXRXBUFCNT
103{
104 /** The current counter value. */
105 uint32_t iCnt;
106 /** Number of bytes left to receive/transmit. */
107 size_t cbTxRxLeft;
108 /** The offset into the buffer to receive to/send from. */
109 size_t offBuf;
110 /** Maximum size to send/receive before processing is needed again. */
111 size_t cbTxRxMax;
112 /** The data buffer. */
113 uint8_t abBuf[_1K];
114} SERIALTESTTXRXBUFCNT;
115/** Pointer to a TX/RX buffer. */
116typedef SERIALTESTTXRXBUFCNT *PSERIALTESTTXRXBUFCNT;
117
118
119/*********************************************************************************************************************************
120* Global Variables *
121*********************************************************************************************************************************/
122
123
124/** Command line parameters */
125static const RTGETOPTDEF g_aCmdOptions[] =
126{
127 {"--device", 'd', RTGETOPT_REQ_STRING },
128 {"--baudrate", 'b', RTGETOPT_REQ_UINT32 },
129 {"--parity", 'p', RTGETOPT_REQ_STRING },
130 {"--databits", 'c', RTGETOPT_REQ_UINT32 },
131 {"--stopbits", 's', RTGETOPT_REQ_STRING },
132 {"--loopbackdevice", 'l', RTGETOPT_REQ_STRING },
133 {"--tests", 't', RTGETOPT_REQ_STRING },
134 {"--txbytes", 'x', RTGETOPT_REQ_UINT32 },
135 {"--help", 'h', RTGETOPT_REQ_NOTHING}
136};
137
138
139static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest);
140
141/** Implemented tests. */
142static const SERIALTESTDESC g_aSerialTests[] =
143{
144 {"readwrite", "Simple Read/Write test", serialTestRunReadWrite }
145};
146
147/** The test handle. */
148static RTTEST g_hTest = NIL_RTTEST;
149/** The serial port handle. */
150static RTSERIALPORT g_hSerialPort = NIL_RTSERIALPORT;
151/** The loopback serial port handle if configured. */
152static RTSERIALPORT g_hSerialPortLoopback = NIL_RTSERIALPORT;
153/** Number of bytes to transmit for read/write tests. */
154static size_t g_cbTx = _1M;
155/** The config used. */
156static RTSERIALPORTCFG g_SerialPortCfg =
157{
158 /* uBaudRate */
159 115200,
160 /* enmParity */
161 RTSERIALPORTPARITY_NONE,
162 /* enmDataBitCount */
163 RTSERIALPORTDATABITS_8BITS,
164 /* enmStopBitCount */
165 RTSERIALPORTSTOPBITS_ONE
166};
167
168
169/**
170 * Initializes a TX buffer.
171 *
172 * @returns nothing.
173 * @param pSerBuf The serial buffer to initialize.
174 * @param cbTx Maximum number of bytes to transmit.
175 */
176static void serialTestTxBufInit(PSERIALTESTTXRXBUFCNT pSerBuf, size_t cbTx)
177{
178 pSerBuf->iCnt = 0;
179 pSerBuf->offBuf = 0;
180 pSerBuf->cbTxRxMax = 0;
181 pSerBuf->cbTxRxLeft = cbTx;
182 RT_ZERO(pSerBuf->abBuf);
183}
184
185
186/**
187 * Initializes a RX buffer.
188 *
189 * @returns nothing.
190 * @param pSerBuf The serial buffer to initialize.
191 * @param cbRx Maximum number of bytes to receive.
192 */
193static void serialTestRxBufInit(PSERIALTESTTXRXBUFCNT pSerBuf, size_t cbRx)
194{
195 pSerBuf->iCnt = 0;
196 pSerBuf->offBuf = 0;
197 pSerBuf->cbTxRxMax = sizeof(pSerBuf->abBuf);
198 pSerBuf->cbTxRxLeft = cbRx;
199 RT_ZERO(pSerBuf->abBuf);
200}
201
202
203/**
204 * Prepares the given TX buffer with data for sending it out.
205 *
206 * @returns nothing.
207 * @param pSerBuf The TX buffer pointer.
208 */
209static void serialTestTxBufPrepare(PSERIALTESTTXRXBUFCNT pSerBuf)
210{
211 /* Move the data to the front to make room at the end to fill. */
212 if (pSerBuf->offBuf)
213 {
214 memmove(&pSerBuf->abBuf[0], &pSerBuf->abBuf[pSerBuf->offBuf], sizeof(pSerBuf->abBuf) - pSerBuf->offBuf);
215 pSerBuf->offBuf = 0;
216 }
217
218 /* Fill up with data. */
219 uint32_t offData = 0;
220 while (pSerBuf->cbTxRxMax + sizeof(uint32_t) <= sizeof(pSerBuf->abBuf))
221 {
222 pSerBuf->iCnt++;
223 *(uint32_t *)&pSerBuf->abBuf[pSerBuf->offBuf + offData] = pSerBuf->iCnt;
224 pSerBuf->cbTxRxMax += sizeof(uint32_t);
225 offData += sizeof(uint32_t);
226 }
227}
228
229
230/**
231 * Sends a new batch of data from the TX buffer preapring new data if required.
232 *
233 * @returns IPRT status code.
234 * @param hSerialPort The serial port handle to send the data to.
235 * @param pSerBuf The TX buffer pointer.
236 */
237static int serialTestTxBufSend(RTSERIALPORT hSerialPort, PSERIALTESTTXRXBUFCNT pSerBuf)
238{
239 int rc = VINF_SUCCESS;
240
241 if (pSerBuf->cbTxRxLeft)
242 {
243 if (!pSerBuf->cbTxRxMax)
244 serialTestTxBufPrepare(pSerBuf);
245
246 size_t cbToWrite = RT_MIN(pSerBuf->cbTxRxMax, pSerBuf->cbTxRxLeft);
247 size_t cbWritten = 0;
248 rc = RTSerialPortWriteNB(hSerialPort, &pSerBuf->abBuf[pSerBuf->offBuf], cbToWrite, &cbWritten);
249 if (RT_SUCCESS(rc))
250 {
251 pSerBuf->cbTxRxMax -= cbWritten;
252 pSerBuf->offBuf += cbWritten;
253 pSerBuf->cbTxRxLeft -= cbWritten;
254 }
255 }
256
257 return rc;
258}
259
260
261/**
262 * Receives dat from the given serial port into the supplied RX buffer and does some validity checking.
263 *
264 * @returns IPRT status code.
265 * @param hSerialPort The serial port handle to receive data from.
266 * @param pSerBuf The RX buffer pointer.
267 */
268static int serialTestRxBufRecv(RTSERIALPORT hSerialPort, PSERIALTESTTXRXBUFCNT pSerBuf)
269{
270 int rc = VINF_SUCCESS;
271
272 if (pSerBuf->cbTxRxLeft)
273 {
274 size_t cbToRead = RT_MIN(pSerBuf->cbTxRxMax, pSerBuf->cbTxRxLeft);
275 size_t cbRead = 0;
276 rc = RTSerialPortReadNB(hSerialPort, &pSerBuf->abBuf[pSerBuf->offBuf], cbToRead, &cbRead);
277 if (RT_SUCCESS(rc))
278 {
279 pSerBuf->offBuf += cbRead;
280 pSerBuf->cbTxRxMax -= cbRead;
281 pSerBuf->cbTxRxLeft -= cbRead;
282 }
283 }
284
285 return rc;
286}
287
288
289/**
290 * Verifies the data in the given RX buffer for correct transmission.
291 *
292 * @returns nothing.
293 * @param hTest The test handle to report errors to.
294 * @param pSerBuf The RX buffer pointer.
295 * @param iCntTx The current TX counter value the RX buffer should never get ahead of.
296 */
297static void serialTestRxBufVerify(RTTEST hTest, PSERIALTESTTXRXBUFCNT pSerBuf, uint32_t iCntTx)
298{
299 uint32_t offRx = 0;
300
301 while (offRx + sizeof(uint32_t) < pSerBuf->offBuf)
302 {
303 uint32_t u32Val = *(uint32_t *)&pSerBuf->abBuf[offRx];
304 offRx += sizeof(uint32_t);
305
306 if (RT_UNLIKELY(u32Val != ++pSerBuf->iCnt))
307 RTTestFailed(hTest, "Data corruption/loss detected, expected counter value %u got %u\n",
308 pSerBuf->iCnt, u32Val);
309 }
310
311 if (RT_UNLIKELY(pSerBuf->iCnt > iCntTx))
312 RTTestFailed(hTest, "Overtook the send buffer, expected maximum counter value %u got %u\n",
313 iCntTx, pSerBuf->iCnt);
314
315 /* Remove processed data from the buffer and move the rest to the front. */
316 if (offRx)
317 {
318 memmove(&pSerBuf->abBuf[0], &pSerBuf->abBuf[offRx], sizeof(pSerBuf->abBuf) - offRx);
319 pSerBuf->offBuf -= offRx;
320 pSerBuf->cbTxRxMax += offRx;
321 }
322}
323
324
325/**
326 * Runs a simple read/write test.
327 *
328 * @returns IPRT status code.
329 * @param pSerialTest The serial test configuration.
330 */
331static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest)
332{
333 uint64_t tsStart = RTTimeMilliTS();
334 SERIALTESTTXRXBUFCNT SerBufTx;
335 SERIALTESTTXRXBUFCNT SerBufRx;
336
337 serialTestTxBufInit(&SerBufTx, g_cbTx);
338 serialTestRxBufInit(&SerBufRx, g_cbTx);
339
340 int rc = serialTestTxBufSend(pSerialTest->hSerialPort, &SerBufTx);
341 while ( RT_SUCCESS(rc)
342 && ( SerBufTx.cbTxRxLeft
343 || SerBufRx.cbTxRxLeft))
344 {
345 uint32_t fEvts = 0;
346 uint32_t fEvtsQuery = 0;
347 if (SerBufTx.cbTxRxLeft)
348 fEvtsQuery |= RTSERIALPORT_EVT_F_DATA_TX;
349 if (SerBufRx.cbTxRxLeft)
350 fEvtsQuery |= RTSERIALPORT_EVT_F_DATA_RX;
351
352 rc = RTSerialPortEvtPoll(pSerialTest->hSerialPort, fEvtsQuery, &fEvts, RT_INDEFINITE_WAIT);
353 if (RT_FAILURE(rc))
354 break;
355
356 if (fEvts & RTSERIALPORT_EVT_F_DATA_RX)
357 {
358 rc = serialTestRxBufRecv(pSerialTest->hSerialPort, &SerBufRx);
359 if (RT_FAILURE(rc))
360 break;
361
362 serialTestRxBufVerify(pSerialTest->hTest, &SerBufRx, SerBufTx.iCnt);
363 }
364 if ( RT_SUCCESS(rc)
365 && (fEvts & RTSERIALPORT_EVT_F_DATA_TX))
366 rc = serialTestTxBufSend(pSerialTest->hSerialPort, &SerBufTx);
367 }
368
369 uint64_t tsRuntime = RTTimeMilliTS() - tsStart;
370 tsRuntime /= 1000; /* Seconds */
371 RTTestValue(pSerialTest->hTest, "Throughput", g_cbTx / tsRuntime, RTTESTUNIT_BYTES_PER_SEC);
372
373 return rc;
374}
375
376
377/**
378 * Returns an array of test descriptors get from the given string.
379 *
380 * @returns Pointer to the array of test descriptors.
381 * @param pszTests The string containing the tests separated with ':'.
382 */
383static PSERIALTESTDESC serialTestSelectFromCmdLine(const char *pszTests)
384{
385 size_t cTests = 1;
386
387 const char *pszNext = strchr(pszTests, ':');
388 while (pszNext)
389 {
390 pszNext++;
391 cTests++;
392 pszNext = strchr(pszNext, ':');
393 }
394
395 PSERIALTESTDESC paTests = (PSERIALTESTDESC)RTMemAllocZ((cTests + 1) * sizeof(SERIALTESTDESC));
396 if (RT_LIKELY(paTests))
397 {
398 uint32_t iTest = 0;
399
400 pszNext = strchr(pszTests, ':');
401 while (pszNext)
402 {
403 bool fFound = false;
404
405 pszNext++; /* Skip : character. */
406
407 for (unsigned i = 0; i < RT_ELEMENTS(g_aSerialTests); i++)
408 {
409 if (!RTStrNICmp(pszTests, g_aSerialTests[i].pszId, pszNext - pszTests - 1))
410 {
411 memcpy(&paTests[iTest], &g_aSerialTests[i], sizeof(SERIALTESTDESC));
412 fFound = true;
413 break;
414 }
415 }
416
417 if (RT_UNLIKELY(!fFound))
418 {
419 RTPrintf("Testcase \"%.*s\" not known\n", pszNext - pszTests - 1, pszTests);
420 RTMemFree(paTests);
421 return NULL;
422 }
423
424 pszTests = pszNext;
425 pszNext = strchr(pszTests, ':');
426 }
427
428 /* Fill last descriptor. */
429 bool fFound = false;
430 for (unsigned i = 0; i < RT_ELEMENTS(g_aSerialTests); i++)
431 {
432 if (!RTStrICmp(pszTests, g_aSerialTests[i].pszId))
433 {
434 memcpy(&paTests[iTest], &g_aSerialTests[i], sizeof(SERIALTESTDESC));
435 fFound = true;
436 break;
437 }
438 }
439
440 if (RT_UNLIKELY(!fFound))
441 {
442 RTPrintf("Testcase \"%s\" not known\n", pszTests);
443 RTMemFree(paTests);
444 paTests = NULL;
445 }
446 }
447 else
448 RTPrintf("Failed to allocate test descriptors for %u selected tests\n", cTests);
449
450 return paTests;
451}
452
453
454/**
455 * Shows tool usage text.
456 */
457static void serialTestUsage(PRTSTREAM pStrm)
458{
459 char szExec[RTPATH_MAX];
460 RTStrmPrintf(pStrm, "usage: %s [options]\n",
461 RTPathFilename(RTProcGetExecutablePath(szExec, sizeof(szExec))));
462 RTStrmPrintf(pStrm, "\n");
463 RTStrmPrintf(pStrm, "options: \n");
464
465
466 for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdOptions); i++)
467 {
468 const char *pszHelp;
469 switch (g_aCmdOptions[i].iShort)
470 {
471 case 'h':
472 pszHelp = "Displays this help and exit";
473 break;
474 case 'd':
475 pszHelp = "Use the specified serial port device";
476 break;
477 case 'b':
478 pszHelp = "Use the given baudrate";
479 break;
480 case 'p':
481 pszHelp = "Use the given parity, valid modes are: none, even, odd, mark, space";
482 break;
483 case 'c':
484 pszHelp = "Use the given data bitcount, valid are: 5, 6, 7, 8";
485 break;
486 case 's':
487 pszHelp = "Use the given stop bitcount, valid are: 1, 1.5, 2";
488 break;
489 case 'l':
490 pszHelp = "Use the given serial port device as the loopback device";
491 break;
492 case 't':
493 pszHelp = "The tests to run separated by ':'";
494 break;
495 case 'x':
496 pszHelp = "Number of bytes to transmit during read/write tests";
497 break;
498 default:
499 pszHelp = "Option undocumented";
500 break;
501 }
502 char szOpt[256];
503 RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdOptions[i].pszLong, g_aCmdOptions[i].iShort);
504 RTStrmPrintf(pStrm, " %-30s%s\n", szOpt, pszHelp);
505 }
506}
507
508
509int main(int argc, char *argv[])
510{
511 /*
512 * Init IPRT and globals.
513 */
514 int rc = RTTestInitAndCreate("SerialTest", &g_hTest);
515 if (rc)
516 return rc;
517
518 /*
519 * Default values.
520 */
521 const char *pszDevice = NULL;
522 const char *pszDeviceLoopback = NULL;
523 PSERIALTESTDESC paTests = NULL;
524
525 RTGETOPTUNION ValueUnion;
526 RTGETOPTSTATE GetState;
527 RTGetOptInit(&GetState, argc, argv, g_aCmdOptions, RT_ELEMENTS(g_aCmdOptions), 1, 0 /* fFlags */);
528 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
529 {
530 switch (rc)
531 {
532 case 'h':
533 serialTestUsage(g_pStdOut);
534 return RTEXITCODE_SUCCESS;
535 case 'd':
536 pszDevice = ValueUnion.psz;
537 break;
538 case 'l':
539 pszDeviceLoopback = ValueUnion.psz;
540 break;
541 case 'b':
542 g_SerialPortCfg.uBaudRate = ValueUnion.u32;
543 break;
544 case 'p':
545 if (!RTStrICmp(ValueUnion.psz, "none"))
546 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_NONE;
547 else if (!RTStrICmp(ValueUnion.psz, "even"))
548 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_EVEN;
549 else if (!RTStrICmp(ValueUnion.psz, "odd"))
550 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_ODD;
551 else if (!RTStrICmp(ValueUnion.psz, "mark"))
552 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_MARK;
553 else if (!RTStrICmp(ValueUnion.psz, "space"))
554 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_SPACE;
555 else
556 {
557 RTPrintf("Unknown parity \"%s\" given\n", ValueUnion.psz);
558 return RTEXITCODE_FAILURE;
559 }
560 break;
561 case 'c':
562 if (!RTStrICmp(ValueUnion.psz, "5"))
563 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_5BITS;
564 else if (!RTStrICmp(ValueUnion.psz, "6"))
565 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_6BITS;
566 else if (!RTStrICmp(ValueUnion.psz, "7"))
567 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_7BITS;
568 else if (!RTStrICmp(ValueUnion.psz, "8"))
569 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_8BITS;
570 else
571 {
572 RTPrintf("Unknown data bitcount \"%s\" given\n", ValueUnion.psz);
573 return RTEXITCODE_FAILURE;
574 }
575 break;
576 case 's':
577 if (!RTStrICmp(ValueUnion.psz, "1"))
578 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONE;
579 else if (!RTStrICmp(ValueUnion.psz, "1.5"))
580 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONEPOINTFIVE;
581 else if (!RTStrICmp(ValueUnion.psz, "2"))
582 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_TWO;
583 else
584 {
585 RTPrintf("Unknown stop bitcount \"%s\" given\n", ValueUnion.psz);
586 return RTEXITCODE_FAILURE;
587 }
588 break;
589 case 't':
590 paTests = serialTestSelectFromCmdLine(ValueUnion.psz);
591 if (!paTests)
592 return RTEXITCODE_FAILURE;
593 break;
594 case 'x':
595 g_cbTx = ValueUnion.u32;
596 break;
597 default:
598 return RTGetOptPrintError(rc, &ValueUnion);
599 }
600 }
601
602 if (!paTests)
603 {
604 /* Select all. */
605 paTests = (PSERIALTESTDESC)RTMemAllocZ((RT_ELEMENTS(g_aSerialTests) + 1) * sizeof(SERIALTESTDESC));
606 if (RT_UNLIKELY(!paTests))
607 {
608 RTPrintf("Failed to allocate memory for test descriptors\n");
609 return RTEXITCODE_FAILURE;
610 }
611 memcpy(paTests, &g_aSerialTests[0], RT_ELEMENTS(g_aSerialTests) * sizeof(SERIALTESTDESC));
612 }
613
614 /*
615 * Start testing.
616 */
617 RTTestBanner(g_hTest);
618
619 if (pszDevice)
620 {
621 uint32_t fFlags = RTSERIALPORT_OPEN_F_READ
622 | RTSERIALPORT_OPEN_F_WRITE
623 | RTSERIALPORT_OPEN_F_SUPPORT_STATUS_LINE_MONITORING;
624
625 RTTestSub(g_hTest, "Opening device");
626 rc = RTSerialPortOpen(&g_hSerialPort, pszDevice, fFlags);
627 if (RT_SUCCESS(rc))
628 {
629 if (pszDeviceLoopback)
630 {
631 RTTestSub(g_hTest, "Opening loopback device");
632 rc = RTSerialPortOpen(&g_hSerialPortLoopback, pszDeviceLoopback, fFlags);
633 if (RT_FAILURE(rc))
634 RTTestFailed(g_hTest, "Opening loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
635 }
636
637 if (RT_SUCCESS(rc))
638 {
639 RTTestSub(g_hTest, "Setting serial port configuration");
640
641 rc = RTSerialPortCfgSet(g_hSerialPort, &g_SerialPortCfg ,NULL);
642 if (RT_SUCCESS(rc))
643 {
644 if (pszDeviceLoopback)
645 {
646 RTTestSub(g_hTest, "Setting serial port configuration for loopback device");
647 rc = RTSerialPortCfgSet(g_hSerialPortLoopback,&g_SerialPortCfg ,NULL);
648 if (RT_FAILURE(rc))
649 RTTestFailed(g_hTest, "Setting configuration of loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
650 }
651
652 if (RT_SUCCESS(rc))
653 {
654 SERIALTEST Test;
655 PSERIALTESTDESC pTest = &paTests[0];
656
657 Test.hTest = g_hTest;
658 Test.hSerialPort = g_hSerialPort;
659 Test.pSerialCfg = &g_SerialPortCfg;
660
661 while (pTest->pszId)
662 {
663 RTTestSub(g_hTest, pTest->pszDesc);
664 rc = pTest->pfnRun(&Test);
665 if (RT_FAILURE(rc))
666 RTTestFailed(g_hTest, "Running test \"%s\" failed with %Rrc\n", pTest->pszId, rc);
667
668 RTTestSubDone(g_hTest);
669 pTest++;
670 }
671 }
672 }
673 else
674 RTTestFailed(g_hTest, "Setting configuration of device \"%s\" failed with %Rrc\n", pszDevice, rc);
675
676 RTSerialPortClose(g_hSerialPort);
677 }
678 }
679 else
680 RTTestFailed(g_hTest, "Opening device \"%s\" failed with %Rrc\n", pszDevice, rc);
681 }
682 else
683 RTTestFailed(g_hTest, "No device given on command line\n");
684
685 RTMemFree(paTests);
686 RTEXITCODE rcExit = RTTestSummaryAndDestroy(g_hTest);
687 return rcExit;
688}
689
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette