VirtualBox

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

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

ValidationKit/utils/SerialTest: Implement simple read/write test

  • 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 70634 2018-01-18 15:27:00Z 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* Global Variables *
120*********************************************************************************************************************************/
121
122
123/** Command line parameters */
124static const RTGETOPTDEF g_aCmdOptions[] =
125{
126 {"--device", 'd', RTGETOPT_REQ_STRING },
127 {"--baudrate", 'b', RTGETOPT_REQ_UINT32 },
128 {"--parity", 'p', RTGETOPT_REQ_STRING },
129 {"--databits", 'c', RTGETOPT_REQ_UINT32 },
130 {"--stopbits", 's', RTGETOPT_REQ_STRING },
131 {"--loopbackdevice", 'l', RTGETOPT_REQ_STRING },
132 {"--tests", 't', RTGETOPT_REQ_STRING },
133 {"--txbytes", 'x', RTGETOPT_REQ_UINT32 },
134 {"--help", 'h', RTGETOPT_REQ_NOTHING}
135};
136
137
138static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest);
139
140/** Implemented tests. */
141static const SERIALTESTDESC g_aSerialTests[] =
142{
143 {"readwrite", "Simple Read/Write test", serialTestRunReadWrite }
144};
145
146/** The test handle. */
147static RTTEST g_hTest = NIL_RTTEST;
148/** The serial port handle. */
149static RTSERIALPORT g_hSerialPort = NIL_RTSERIALPORT;
150/** The loopback serial port handle if configured. */
151static RTSERIALPORT g_hSerialPortLoopback = NIL_RTSERIALPORT;
152/** Number of bytes to transmit for read/write tests. */
153static size_t g_cbTx = _1M;
154/** The config used. */
155static RTSERIALPORTCFG g_SerialPortCfg =
156{
157 /* uBaudRate */
158 115200,
159 /* enmParity */
160 RTSERIALPORTPARITY_NONE,
161 /* enmDataBitCount */
162 RTSERIALPORTDATABITS_8BITS,
163 /* enmStopBitCount */
164 RTSERIALPORTSTOPBITS_ONE
165};
166
167
168/**
169 * Initializes a TX buffer.
170 *
171 * @returns nothing.
172 * @param pSerBuf The serial buffer to initialize.
173 * @param cbTx Maximum number of bytes to transmit.
174 */
175static void serialTestTxBufInit(PSERIALTESTTXRXBUFCNT pSerBuf, size_t cbTx)
176{
177 pSerBuf->iCnt = 0;
178 pSerBuf->offBuf = 0;
179 pSerBuf->cbTxRxMax = 0;
180 pSerBuf->cbTxRxLeft = cbTx;
181 RT_ZERO(pSerBuf->abBuf);
182}
183
184
185/**
186 * Initializes a RX buffer.
187 *
188 * @returns nothing.
189 * @param pSerBuf The serial buffer to initialize.
190 * @param cbRx Maximum number of bytes to receive.
191 */
192static void serialTestRxBufInit(PSERIALTESTTXRXBUFCNT pSerBuf, size_t cbRx)
193{
194 pSerBuf->iCnt = 0;
195 pSerBuf->offBuf = 0;
196 pSerBuf->cbTxRxMax = sizeof(pSerBuf->abBuf);
197 pSerBuf->cbTxRxLeft = cbRx;
198 RT_ZERO(pSerBuf->abBuf);
199}
200
201
202/**
203 * Prepares the given TX buffer with data for sending it out.
204 *
205 * @returns nothing.
206 * @param pSerBuf The TX buffer pointer.
207 */
208static void serialTestTxBufPrepare(PSERIALTESTTXRXBUFCNT pSerBuf)
209{
210 /* Move the data to the front to make room at the end to fill. */
211 if (pSerBuf->offBuf)
212 {
213 memmove(&pSerBuf->abBuf[0], &pSerBuf->abBuf[pSerBuf->offBuf], sizeof(pSerBuf->abBuf) - pSerBuf->offBuf);
214 pSerBuf->offBuf = 0;
215 }
216
217 /* Fill up with data. */
218 uint32_t offData = 0;
219 while (pSerBuf->cbTxRxMax + sizeof(uint32_t) <= sizeof(pSerBuf->abBuf))
220 {
221 pSerBuf->iCnt++;
222 *(uint32_t *)&pSerBuf->abBuf[pSerBuf->offBuf + offData] = pSerBuf->iCnt;
223 pSerBuf->cbTxRxMax += sizeof(uint32_t);
224 offData += sizeof(uint32_t);
225 }
226}
227
228
229/**
230 * Sends a new batch of data from the TX buffer preapring new data if required.
231 *
232 * @returns IPRT status code.
233 * @param hSerialPort The serial port handle to send the data to.
234 * @param pSerBuf The TX buffer pointer.
235 */
236static int serialTestTxBufSend(RTSERIALPORT hSerialPort, PSERIALTESTTXRXBUFCNT pSerBuf)
237{
238 int rc = VINF_SUCCESS;
239
240 if (pSerBuf->cbTxRxLeft)
241 {
242 if (!pSerBuf->cbTxRxMax)
243 serialTestTxBufPrepare(pSerBuf);
244
245 size_t cbToWrite = RT_MIN(pSerBuf->cbTxRxMax, pSerBuf->cbTxRxLeft);
246 size_t cbWritten = 0;
247 rc = RTSerialPortWriteNB(hSerialPort, &pSerBuf->abBuf[pSerBuf->offBuf], cbToWrite, &cbWritten);
248 if (RT_SUCCESS(rc))
249 {
250 pSerBuf->cbTxRxMax -= cbWritten;
251 pSerBuf->offBuf += cbWritten;
252 pSerBuf->cbTxRxLeft -= cbWritten;
253 }
254 }
255
256 return rc;
257}
258
259
260/**
261 * Receives dat from the given serial port into the supplied RX buffer and does some validity checking.
262 *
263 * @returns IPRT status code.
264 * @param hSerialPort The serial port handle to receive data from.
265 * @param pSerBuf The RX buffer pointer.
266 */
267static int serialTestRxBufRecv(RTSERIALPORT hSerialPort, PSERIALTESTTXRXBUFCNT pSerBuf)
268{
269 int rc = VINF_SUCCESS;
270
271 if (pSerBuf->cbTxRxLeft)
272 {
273 size_t cbToRead = RT_MIN(pSerBuf->cbTxRxMax, pSerBuf->cbTxRxLeft);
274 size_t cbRead = 0;
275 rc = RTSerialPortReadNB(hSerialPort, &pSerBuf->abBuf[pSerBuf->offBuf], cbToRead, &cbRead);
276 if (RT_SUCCESS(rc))
277 {
278 pSerBuf->offBuf += cbRead;
279 pSerBuf->cbTxRxMax -= cbRead;
280 pSerBuf->cbTxRxLeft -= cbRead;
281 }
282 }
283
284 return rc;
285}
286
287
288/**
289 * Verifies the data in the given RX buffer for correct transmission.
290 *
291 * @returns nothing.
292 * @param hTest The test handle to report errors to.
293 * @param pSerBuf The RX buffer pointer.
294 * @param iCntTx The current TX counter value the RX buffer should never get ahead of.
295 */
296static void serialTestRxBufVerify(RTTEST hTest, PSERIALTESTTXRXBUFCNT pSerBuf, uint32_t iCntTx)
297{
298 uint32_t offRx = 0;
299
300 while (offRx + sizeof(uint32_t) < pSerBuf->offBuf)
301 {
302 uint32_t u32Val = *(uint32_t *)&pSerBuf->abBuf[offRx];
303 offRx += sizeof(uint32_t);
304
305 if (RT_UNLIKELY(u32Val != ++pSerBuf->iCnt))
306 RTTestFailed(hTest, "Data corruption/loss detected, expected counter value %u got %u\n",
307 pSerBuf->iCnt, u32Val);
308 }
309
310 if (RT_UNLIKELY(pSerBuf->iCnt > iCntTx))
311 RTTestFailed(hTest, "Overtook the send buffer, expected maximum counter value %u got %u\n",
312 iCntTx, pSerBuf->iCnt);
313
314 /* Remove processed data from the buffer and move the rest to the front. */
315 if (offRx)
316 {
317 memmove(&pSerBuf->abBuf[0], &pSerBuf->abBuf[offRx], sizeof(pSerBuf->abBuf) - offRx);
318 pSerBuf->offBuf -= offRx;
319 pSerBuf->cbTxRxMax += offRx;
320 }
321}
322
323
324/**
325 * Runs a simple read/write test.
326 *
327 * @returns IPRT status code.
328 * @param pSerialTest The serial test configuration.
329 */
330static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest)
331{
332 uint64_t tsStart = RTTimeMilliTS();
333 SERIALTESTTXRXBUFCNT SerBufTx;
334 SERIALTESTTXRXBUFCNT SerBufRx;
335
336 serialTestTxBufInit(&SerBufTx, g_cbTx);
337 serialTestRxBufInit(&SerBufRx, g_cbTx);
338
339 int rc = serialTestTxBufSend(pSerialTest->hSerialPort, &SerBufTx);
340 while ( RT_SUCCESS(rc)
341 && ( SerBufTx.cbTxRxLeft
342 || SerBufRx.cbTxRxLeft))
343 {
344 uint32_t fEvts = 0;
345 uint32_t fEvtsQuery = 0;
346 if (SerBufTx.cbTxRxLeft)
347 fEvtsQuery |= RTSERIALPORT_EVT_F_DATA_TX;
348 if (SerBufRx.cbTxRxLeft)
349 fEvtsQuery |= RTSERIALPORT_EVT_F_DATA_RX;
350
351 rc = RTSerialPortEvtPoll(pSerialTest->hSerialPort, fEvtsQuery, &fEvts, RT_INDEFINITE_WAIT);
352 if (RT_FAILURE(rc))
353 break;
354
355 if (fEvts & RTSERIALPORT_EVT_F_DATA_RX)
356 {
357 rc = serialTestRxBufRecv(pSerialTest->hSerialPort, &SerBufRx);
358 if (RT_FAILURE(rc))
359 break;
360
361 serialTestRxBufVerify(pSerialTest->hTest, &SerBufRx, SerBufTx.iCnt);
362 }
363 if ( RT_SUCCESS(rc)
364 && (fEvts & RTSERIALPORT_EVT_F_DATA_TX))
365 rc = serialTestTxBufSend(pSerialTest->hSerialPort, &SerBufTx);
366 }
367
368 uint64_t tsRuntime = RTTimeMilliTS() - tsStart;
369 tsRuntime /= 1000; /* Seconds */
370 RTTestValue(pSerialTest->hTest, "Throughput", g_cbTx / tsRuntime, RTTESTUNIT_BYTES_PER_SEC);
371
372 return rc;
373}
374
375
376/**
377 * Returns an array of test descriptors get from the given string.
378 *
379 * @returns Pointer to the array of test descriptors.
380 * @param pszTests The string containing the tests separated with ':'.
381 */
382static PSERIALTESTDESC serialTestSelectFromCmdLine(const char *pszTests)
383{
384 size_t cTests = 1;
385
386 const char *pszNext = strchr(pszTests, ':');
387 while (pszNext)
388 {
389 pszNext++;
390 cTests++;
391 pszNext = strchr(pszNext, ':');
392 }
393
394 PSERIALTESTDESC paTests = (PSERIALTESTDESC)RTMemAllocZ((cTests + 1) * sizeof(SERIALTESTDESC));
395 if (RT_LIKELY(paTests))
396 {
397 uint32_t iTest = 0;
398
399 pszNext = strchr(pszTests, ':');
400 while (pszNext)
401 {
402 bool fFound = false;
403
404 pszNext++; /* Skip : character. */
405
406 for (unsigned i = 0; i < RT_ELEMENTS(g_aSerialTests); i++)
407 {
408 if (!RTStrNICmp(pszTests, g_aSerialTests[i].pszId, pszNext - pszTests - 1))
409 {
410 memcpy(&paTests[iTest], &g_aSerialTests[i], sizeof(SERIALTESTDESC));
411 fFound = true;
412 break;
413 }
414 }
415
416 if (RT_UNLIKELY(!fFound))
417 {
418 RTPrintf("Testcase \"%.*s\" not known\n", pszNext - pszTests - 1, pszTests);
419 RTMemFree(paTests);
420 return NULL;
421 }
422
423 pszTests = pszNext;
424 pszNext = strchr(pszTests, ':');
425 }
426
427 /* Fill last descriptor. */
428 bool fFound = false;
429 for (unsigned i = 0; i < RT_ELEMENTS(g_aSerialTests); i++)
430 {
431 if (!RTStrICmp(pszTests, g_aSerialTests[i].pszId))
432 {
433 memcpy(&paTests[iTest], &g_aSerialTests[i], sizeof(SERIALTESTDESC));
434 fFound = true;
435 break;
436 }
437 }
438
439 if (RT_UNLIKELY(!fFound))
440 {
441 RTPrintf("Testcase \"%s\" not known\n", pszTests);
442 RTMemFree(paTests);
443 paTests = NULL;
444 }
445 }
446 else
447 RTPrintf("Failed to allocate test descriptors for %u selected tests\n", cTests);
448
449 return paTests;
450}
451
452
453/**
454 * Shows tool usage text.
455 */
456static void serialTestUsage(PRTSTREAM pStrm)
457{
458 char szExec[RTPATH_MAX];
459 RTStrmPrintf(pStrm, "usage: %s [options]\n",
460 RTPathFilename(RTProcGetExecutablePath(szExec, sizeof(szExec))));
461 RTStrmPrintf(pStrm, "\n");
462 RTStrmPrintf(pStrm, "options: \n");
463
464
465 for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdOptions); i++)
466 {
467 const char *pszHelp;
468 switch (g_aCmdOptions[i].iShort)
469 {
470 case 'h':
471 pszHelp = "Displays this help and exit";
472 break;
473 case 'd':
474 pszHelp = "Use the specified serial port device";
475 break;
476 case 'b':
477 pszHelp = "Use the given baudrate";
478 break;
479 case 'p':
480 pszHelp = "Use the given parity, valid modes are: none, even, odd, mark, space";
481 break;
482 case 'c':
483 pszHelp = "Use the given data bitcount, valid are: 5, 6, 7, 8";
484 break;
485 case 's':
486 pszHelp = "Use the given stop bitcount, valid are: 1, 1.5, 2";
487 break;
488 case 'l':
489 pszHelp = "Use the given serial port device as the loopback device";
490 break;
491 case 't':
492 pszHelp = "The tests to run separated by ':'";
493 break;
494 case 'x':
495 pszHelp = "Number of bytes to transmit during read/write tests";
496 break;
497 default:
498 pszHelp = "Option undocumented";
499 break;
500 }
501 char szOpt[256];
502 RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdOptions[i].pszLong, g_aCmdOptions[i].iShort);
503 RTStrmPrintf(pStrm, " %-30s%s\n", szOpt, pszHelp);
504 }
505}
506
507
508int main(int argc, char *argv[])
509{
510 /*
511 * Init IPRT and globals.
512 */
513 int rc = RTTestInitAndCreate("SerialTest", &g_hTest);
514 if (rc)
515 return rc;
516
517 /*
518 * Default values.
519 */
520 const char *pszDevice = NULL;
521 const char *pszDeviceLoopback = NULL;
522 PSERIALTESTDESC paTests = NULL;
523
524 RTGETOPTUNION ValueUnion;
525 RTGETOPTSTATE GetState;
526 RTGetOptInit(&GetState, argc, argv, g_aCmdOptions, RT_ELEMENTS(g_aCmdOptions), 1, 0 /* fFlags */);
527 while ((rc = RTGetOpt(&GetState, &ValueUnion)))
528 {
529 switch (rc)
530 {
531 case 'h':
532 serialTestUsage(g_pStdOut);
533 return RTEXITCODE_SUCCESS;
534 case 'd':
535 pszDevice = ValueUnion.psz;
536 break;
537 case 'l':
538 pszDeviceLoopback = ValueUnion.psz;
539 break;
540 case 'b':
541 g_SerialPortCfg.uBaudRate = ValueUnion.u32;
542 break;
543 case 'p':
544 if (!RTStrICmp(ValueUnion.psz, "none"))
545 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_NONE;
546 else if (!RTStrICmp(ValueUnion.psz, "even"))
547 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_EVEN;
548 else if (!RTStrICmp(ValueUnion.psz, "odd"))
549 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_ODD;
550 else if (!RTStrICmp(ValueUnion.psz, "mark"))
551 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_MARK;
552 else if (!RTStrICmp(ValueUnion.psz, "space"))
553 g_SerialPortCfg.enmParity = RTSERIALPORTPARITY_SPACE;
554 else
555 {
556 RTPrintf("Unknown parity \"%s\" given\n", ValueUnion.psz);
557 return RTEXITCODE_FAILURE;
558 }
559 break;
560 case 'c':
561 if (!RTStrICmp(ValueUnion.psz, "5"))
562 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_5BITS;
563 else if (!RTStrICmp(ValueUnion.psz, "6"))
564 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_6BITS;
565 else if (!RTStrICmp(ValueUnion.psz, "7"))
566 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_7BITS;
567 else if (!RTStrICmp(ValueUnion.psz, "8"))
568 g_SerialPortCfg.enmDataBitCount = RTSERIALPORTDATABITS_8BITS;
569 else
570 {
571 RTPrintf("Unknown data bitcount \"%s\" given\n", ValueUnion.psz);
572 return RTEXITCODE_FAILURE;
573 }
574 break;
575 case 's':
576 if (!RTStrICmp(ValueUnion.psz, "1"))
577 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONE;
578 else if (!RTStrICmp(ValueUnion.psz, "1.5"))
579 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_ONEPOINTFIVE;
580 else if (!RTStrICmp(ValueUnion.psz, "2"))
581 g_SerialPortCfg.enmStopBitCount = RTSERIALPORTSTOPBITS_TWO;
582 else
583 {
584 RTPrintf("Unknown stop bitcount \"%s\" given\n", ValueUnion.psz);
585 return RTEXITCODE_FAILURE;
586 }
587 break;
588 case 't':
589 paTests = serialTestSelectFromCmdLine(ValueUnion.psz);
590 if (!paTests)
591 return RTEXITCODE_FAILURE;
592 break;
593 case 'x':
594 g_cbTx = ValueUnion.u32;
595 break;
596 default:
597 return RTGetOptPrintError(rc, &ValueUnion);
598 }
599 }
600
601 if (!paTests)
602 {
603 /* Select all. */
604 paTests = (PSERIALTESTDESC)RTMemAllocZ((RT_ELEMENTS(g_aSerialTests) + 1) * sizeof(SERIALTESTDESC));
605 if (RT_UNLIKELY(!paTests))
606 {
607 RTPrintf("Failed to allocate memory for test descriptors\n");
608 return RTEXITCODE_FAILURE;
609 }
610 memcpy(paTests, &g_aSerialTests[0], RT_ELEMENTS(g_aSerialTests) * sizeof(SERIALTESTDESC));
611 }
612
613 /*
614 * Start testing.
615 */
616 RTTestBanner(g_hTest);
617
618 if (pszDevice)
619 {
620 uint32_t fFlags = RTSERIALPORT_OPEN_F_READ
621 | RTSERIALPORT_OPEN_F_WRITE
622 | RTSERIALPORT_OPEN_F_SUPPORT_STATUS_LINE_MONITORING;
623
624 RTTestSub(g_hTest, "Opening device");
625 rc = RTSerialPortOpen(&g_hSerialPort, pszDevice, fFlags);
626 if (RT_SUCCESS(rc))
627 {
628 if (pszDeviceLoopback)
629 {
630 RTTestSub(g_hTest, "Opening loopback device");
631 rc = RTSerialPortOpen(&g_hSerialPortLoopback, pszDeviceLoopback, fFlags);
632 if (RT_FAILURE(rc))
633 RTTestFailed(g_hTest, "Opening loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
634 }
635
636 if (RT_SUCCESS(rc))
637 {
638 RTTestSub(g_hTest, "Setting serial port configuration");
639
640 rc = RTSerialPortCfgSet(g_hSerialPort, &g_SerialPortCfg ,NULL);
641 if (RT_SUCCESS(rc))
642 {
643 if (pszDeviceLoopback)
644 {
645 RTTestSub(g_hTest, "Setting serial port configuration for loopback device");
646 rc = RTSerialPortCfgSet(g_hSerialPortLoopback,&g_SerialPortCfg ,NULL);
647 if (RT_FAILURE(rc))
648 RTTestFailed(g_hTest, "Setting configuration of loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
649 }
650
651 if (RT_SUCCESS(rc))
652 {
653 SERIALTEST Test;
654 PSERIALTESTDESC pTest = &paTests[0];
655
656 Test.hTest = g_hTest;
657 Test.hSerialPort = g_hSerialPort;
658 Test.pSerialCfg = &g_SerialPortCfg;
659
660 while (pTest->pszId)
661 {
662 RTTestSub(g_hTest, pTest->pszDesc);
663 rc = pTest->pfnRun(&Test);
664 if (RT_FAILURE(rc))
665 RTTestFailed(g_hTest, "Running test \"%s\" failed with %Rrc\n", pTest->pszId, rc);
666
667 RTTestSubDone(g_hTest);
668 pTest++;
669 }
670 }
671 }
672 else
673 RTTestFailed(g_hTest, "Setting configuration of device \"%s\" failed with %Rrc\n", pszDevice, rc);
674
675 RTSerialPortClose(g_hSerialPort);
676 }
677 }
678 else
679 RTTestFailed(g_hTest, "Opening device \"%s\" failed with %Rrc\n", pszDevice, rc);
680 }
681 else
682 RTTestFailed(g_hTest, "No device given on command line\n");
683
684 RTMemFree(paTests);
685 RTEXITCODE rcExit = RTTestSummaryAndDestroy(g_hTest);
686 return rcExit;
687}
688
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