Josh Soref abce91d14b
Spelling (#12954)
* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Advanced Authoring Tests in C++

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: CMake Documentation and Community

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs for networking issues

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: ; otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: a

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: access

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: accessible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: across

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: actively

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: adapters

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: address

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: addresses

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: and

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: appropriate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: argument

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: associated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: attach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: available

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: beginning

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: between

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: binaries

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: bound

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: cannot

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: canonical

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: capabilities

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-insensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-sensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: certified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: command

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: committer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: communication

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: complains

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: configuration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: consumed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: continue

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: converted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: currently

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: customers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: daemon

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: deferred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: definitions

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delimiter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delivered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: dellink

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: derived

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: descriptor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destined

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destruct

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: detach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: differentiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: directories

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disassociate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disposition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distribution

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distro

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: duping

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: emitted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: empty

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: environment

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: every time

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: exclusive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expire

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: explicitly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fall back

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: false

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fastfail

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: filesystem

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: first

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: followed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: for

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionality

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: github

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: greater

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guarantee

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guaranteed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: handles

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hangup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hierarchy

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hogwarts

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hydrated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: icrnl

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: initialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instance

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: intentionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpret

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpreter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: irreversibly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iteration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iterator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: its

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kernel

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kmsg

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: knowledge

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: maximum

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mirrored

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: msftconnecttest

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multi

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multiple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mutable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: namespace

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: notifications

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: outstanding

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: partition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: pass through

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: passthrough

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: performs

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: periodically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: positional

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: precedence

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preexisting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preferring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: prepopulate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: previous

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: privileges

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: process

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: processes

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: programmatically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: protection

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: provided

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reasonable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: receive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: received

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: red hat

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reentrant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: registered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: regularly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: relay

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: release

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: representing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: requests

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: response

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: resurrect

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: retention

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: returned

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: security

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: semaphore

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: service

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: set up

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: setup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: severely

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: should

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: signal

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: similarly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simplified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: single

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: specified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: splitting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: standard

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: stress

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: succeed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: success

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: successfully

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: supplementary

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: synced

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: system

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: take

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: than

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: that opening

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: threadpool

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: to

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: true

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: truncate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: tunneling

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unexpected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: uninitialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unique

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unprivileged

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unregistered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: untrusted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: upgrade

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: utility

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: validating

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: verify

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: visible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: whether

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: winget

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: worker

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: written

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: wslservice

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* format source

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: Ben Hillis <benhillis@gmail.com>
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
2025-07-23 15:19:00 -07:00

1053 lines
27 KiB
C

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
Template.c
Abstract:
This file is a ttys test.
--*/
#include "lxtcommon.h"
#include "unittests.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <termios.h>
#include <stdarg.h>
#include <stdio.h>
#include <poll.h>
#define LXT_NAME "Ttys"
#define LXT_TTYS_LARGE_BUFFER_SIZE (1 * 1024)
#define LXT_TTYS_DEFAULT "/dev/ttyS1"
#define LXT_TTYS_DEFAULT_MINOR (LXT_TTYS_DEV_OFFSET + 1)
#define LXT_TTYS_DEFAULT2 "/dev/ttyS2"
#define LXT_TTYS_DEFAULT2_MINOR (LXT_TTYS_DEV_OFFSET + 2)
#define LXT_TTYS_FORMAT "/dev/ttyS%d"
#define LXT_TTYS_MAX 192
#define LXT_TTYS_DEV_MODE (S_IFCHR | 0660)
#define LXT_TTYS_DEV_MAJOR 4
#define LXT_TTYS_DEV_OFFSET 64
LXT_VARIATION_HANDLER TtysBasicOps;
LXT_VARIATION_HANDLER TtysTermiosBaudParity;
LXT_VARIATION_HANDLER TtysWrite;
LXT_VARIATION_HANDLER TtysWindowSize;
LXT_VARIATION_HANDLER TtysTermiosFlowControl;
LXT_VARIATION_HANDLER TtysWriteRead;
LXT_VARIATION_HANDLER TtysModemIoctls;
//
// Global constants
//
// TtysWriteRead requires two connected serial ports for testing.
//
static const LXT_VARIATION g_LxtVariations[] = {
{"Ttys basic operations", TtysBasicOps},
{"Ttys termios - baud rate and parity", TtysTermiosBaudParity},
{"Ttys write", TtysWrite},
{"Ttys window size", TtysWindowSize},
/* {"Ttys write read", TtysWriteRead}, */
{"Ttys termios - flow control", TtysTermiosFlowControl},
{"Ttys modem ioctls", TtysModemIoctls}};
int TtysTestEntry(int Argc, char* Argv[])
/*++
--*/
{
LXT_ARGS Args;
int Result;
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
ErrorExit:
LxtUninitialize();
return !LXT_SUCCESS(Result);
}
int TtysBasicOps(PLXT_ARGS Args)
/*++
--*/
{
char Buffer[64];
dev_t Device;
int Fd;
char Path[32];
int Index;
int Result;
for (Index = 0; Index < LXT_TTYS_MAX; ++Index)
{
snprintf(Path, sizeof(Path), LXT_TTYS_FORMAT, Index);
unlink(Path);
Device = makedev(LXT_TTYS_DEV_MAJOR, Index + LXT_TTYS_DEV_OFFSET);
LxtCheckErrno(mknod(Path, LXT_TTYS_DEV_MODE, Device));
Fd = open(Path, O_RDWR | O_NONBLOCK, 0);
if (Fd != -1)
{
read(Fd, Buffer, sizeof(Buffer));
write(Fd, Buffer, sizeof(Buffer));
fsync(Fd);
tcflush(Fd, TCIOFLUSH);
LxtClose(Fd);
}
}
Result = LXT_RESULT_SUCCESS;
ErrorExit:
return Result;
}
int TtysTermiosBaudParity(PLXT_ARGS Args)
/*++
--*/
{
int BaudRate;
int BaudRates[] = {B1200, B9600, B9600};
int Cflag;
dev_t Device;
int Iflag;
int Index;
int Fd;
int Result;
struct termios Termios = {0};
struct termios TermiosNew = {0};
Fd = -1;
Result = LXT_RESULT_FAILURE;
//
// Check the default termios values.
//
// N.B. Ignore termios fields that may differ.
//
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
if (Fd == -1)
{
if (errno == EIO)
{
LxtLogInfo("Skipping test %d", errno);
Result = LXT_RESULT_SUCCESS;
}
else
{
LxtLogError("Unexpected error %d", errno);
}
goto ErrorExit;
}
LxtCheckErrno(tcgetattr(Fd, &Termios));
LxtCheckEqual(Termios.c_oflag, 05, "%d");
LxtCheckEqual(Termios.c_lflag, 0105063, "%d");
LxtCheckEqual(Termios.c_line, 0, "%d");
LxtCheckEqual(Termios.c_cc[0], 3, "%d");
LxtCheckEqual(Termios.c_cc[1], 28, "%d");
LxtCheckEqual(Termios.c_cc[2], 127, "%d");
LxtCheckEqual(Termios.c_cc[3], 21, "%d");
LxtCheckEqual(Termios.c_cc[5], 0, "%d");
LxtCheckEqual(Termios.c_cc[6], 1, "%d");
LxtCheckEqual(Termios.c_cc[7], 0, "%d");
LxtCheckEqual(Termios.c_cc[10], 26, "%d");
LxtCheckEqual(Termios.c_cc[11], 0, "%d");
LxtCheckEqual(Termios.c_cc[12], 18, "%d");
LxtCheckEqual(Termios.c_cc[13], 15, "%d");
LxtCheckEqual(Termios.c_cc[14], 23, "%d");
LxtCheckEqual(Termios.c_cc[15], 22, "%d");
LxtCheckEqual(Termios.c_cc[16], 0, "%d");
//
// Set and check the baud rate.
//
BaudRate = cfgetispeed(&Termios);
for (Index = 0; Index < LXT_COUNT_OF(BaudRates); ++Index)
{
cfsetspeed(&Termios, BaudRates[Index]);
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
}
//
// Reset to the original.
//
cfsetspeed(&Termios, BaudRate);
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Set and check the parity enable and type bits
//
// N.B. NT does not support setting input and output parity independently,
// but Linux does.
//
Cflag = Termios.c_cflag;
Iflag = Termios.c_iflag;
//
// No parity, 8 bits
//
Termios.c_iflag &= ~INPCK;
Termios.c_cflag &= ~PARENB;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CMSPAR;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS8;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Even parity, 7 bits
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag &= ~PARODD;
Termios.c_cflag &= ~CMSPAR;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS7;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Odd parity, 7 bits
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag |= PARODD;
Termios.c_cflag &= ~CMSPAR;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS7;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Even parity, 5 bits
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag &= ~PARODD;
Termios.c_cflag &= ~CMSPAR;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS5;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Odd parity, 5 bits, with stop bit
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag |= PARODD;
Termios.c_cflag &= ~CMSPAR;
Termios.c_cflag |= CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS5;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Space parity, 7 bits
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag &= ~PARODD;
Termios.c_cflag |= CMSPAR;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS7;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Mark parity, 7 bits
//
Termios.c_iflag |= INPCK;
Termios.c_cflag |= PARENB;
Termios.c_cflag |= PARODD;
Termios.c_cflag |= CMSPAR;
Termios.c_cflag &= ~CSTOPB;
Termios.c_cflag &= ~CSIZE;
Termios.c_cflag |= CS7;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Reset to the original
//
Termios.c_cflag = Cflag;
Termios.c_iflag = Iflag;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (Fd != -1)
{
LxtClose(Fd);
}
return Result;
}
int TtysWrite(PLXT_ARGS Args)
/*++
--*/
{
char Buffer[64];
int BytesWritten;
dev_t Device;
int Fd;
char Path[32];
struct pollfd PollFd;
int Index;
int Result;
//
// Test non-blocking write paths.
//
// N.B. Blocking can hang if there is no reader.
//
Fd = -1;
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
if (Fd == -1)
{
if (errno == EIO)
{
LxtLogInfo("Skipping test %d", errno);
Result = LXT_RESULT_SUCCESS;
}
else
{
LxtLogError("Unexpected error %d", errno);
}
goto ErrorExit;
}
memset(&PollFd, 0, sizeof(PollFd));
PollFd.fd = Fd;
PollFd.events = POLLIN | POLLOUT | POLLHUP;
LxtCheckErrno(poll(&PollFd, 1, 0));
LxtCheckEqual(PollFd.revents & POLLOUT, POLLOUT, "%d");
errno = 0;
BytesWritten = write(Fd, Buffer, sizeof(Buffer));
if ((BytesWritten != sizeof(Buffer)) && (errno != EAGAIN))
{
LxtLogError("Unexpected BytesWritten %d, %d", BytesWritten, errno);
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (Fd != -1)
{
LxtClose(Fd);
}
return Result;
}
int TtysWindowSize(PLXT_ARGS Args)
/*++
--*/
{
dev_t Device;
int Fd;
char Path[32];
int Result;
struct winsize WindowSize;
struct winsize WindowSizeNew;
//
// Test setting and getting the window size of a serial device.
//
Fd = -1;
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
Fd = open(LXT_TTYS_DEFAULT, O_RDWR, 0);
if (Fd == -1)
{
if (errno == EIO)
{
LxtLogInfo("Skipping test %d", errno);
Result = LXT_RESULT_SUCCESS;
}
else
{
LxtLogError("Unexpected error %d", errno);
}
goto ErrorExit;
}
LxtCheckErrno(ioctl(Fd, TIOCGWINSZ, &WindowSize));
LxtLogInfo("%d, %d", WindowSize.ws_row, WindowSize.ws_col);
WindowSizeNew = WindowSize;
WindowSizeNew.ws_row += 1;
WindowSizeNew.ws_col += 1;
LxtCheckErrno(ioctl(Fd, TIOCSWINSZ, &WindowSizeNew));
LxtCheckErrno(ioctl(Fd, TIOCGWINSZ, &WindowSize));
LxtCheckMemoryEqual(&WindowSize, &WindowSizeNew, sizeof(WindowSize));
memset(&WindowSizeNew, 0, sizeof(WindowSizeNew));
LxtCheckErrno(ioctl(Fd, TIOCSWINSZ, &WindowSizeNew));
LxtCheckErrno(ioctl(Fd, TIOCGWINSZ, &WindowSize));
LxtCheckMemoryEqual(&WindowSize, &WindowSizeNew, sizeof(WindowSize));
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (Fd != -1)
{
LxtClose(Fd);
}
return Result;
}
int TtysTermiosFlowControl(PLXT_ARGS Args)
/*++
--*/
{
int Cflag;
dev_t Device;
int Iflag;
int Index;
int Fd;
int Result;
struct termios Termios = {0};
struct termios TermiosNew = {0};
char VStart;
char VStop;
Fd = -1;
Result = LXT_RESULT_FAILURE;
//
// Check the default termios values.
//
// N.B. Ignore the termios settings that may differ..
//
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
if (Fd == -1)
{
if (errno == EIO)
{
LxtLogInfo("Skipping test %d", errno);
Result = LXT_RESULT_SUCCESS;
}
else
{
LxtLogError("Unexpected error %d", errno);
}
goto ErrorExit;
}
//
// Set and check the parity enable and type bits
//
// N.B. NT does not support setting input and output parity independently,
// but Linux does.
//
LxtCheckErrno(tcgetattr(Fd, &Termios));
Cflag = Termios.c_cflag;
Iflag = Termios.c_iflag;
VStart = Termios.c_cc[VSTART];
VStop = Termios.c_cc[VSTOP];
//
// ixon and ixoff set
//
Termios.c_iflag |= IXON;
Termios.c_iflag |= IXOFF;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// ixon and ixoff not set
//
Termios.c_iflag &= ~IXON;
Termios.c_iflag &= ~IXOFF;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// crtscts set
//
Termios.c_cflag |= CRTSCTS;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// crtscts not set
//
Termios.c_cflag &= ~CRTSCTS;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// clocal not set
//
LxtLogInfo("Clearing clocal");
Termios.c_cflag &= ~CLOCAL;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// clocal set
//
Termios.c_cflag |= CLOCAL;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Flip vstart and vstop
//
LxtLogInfo("Updating vstart and vstop");
Termios.c_cc[VSTART] = VStop;
Termios.c_cc[VSTOP] = VStart;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
//
// Reset to the original
//
LxtLogInfo("Resetting...");
Termios.c_cflag = Cflag;
Termios.c_iflag = Iflag;
Termios.c_cc[VSTART] = VStart;
Termios.c_cc[VSTOP] = VStop;
LxtCheckErrno(tcsetattr(Fd, TCSANOW, &Termios));
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
LxtClose(Fd);
Fd = -1;
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
LxtCheckErrno(tcgetattr(Fd, &TermiosNew));
LxtCheckMemoryEqual(&Termios, &TermiosNew, sizeof(Termios));
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (Fd != -1)
{
LxtClose(Fd);
}
return Result;
}
int TtysWriteReadTransfer(PLXT_ARGS Args, int FdRead, int FdWrite)
/*++
--*/
{
int BytesRead;
int BytesWritten;
int BytesTotal;
pid_t ChildPid;
int Index;
char* RecvBuffer;
int Result;
char* SendBuffer;
ChildPid = -1;
RecvBuffer = NULL;
SendBuffer = NULL;
//
// Allocate a buffer with known data to transfer and a buffer to receive
// the data.
//
SendBuffer = LxtAlloc(LXT_TTYS_LARGE_BUFFER_SIZE);
if (SendBuffer == NULL)
{
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
for (Index = 0; Index < LXT_TTYS_LARGE_BUFFER_SIZE; ++Index)
{
SendBuffer[Index] = (char)Index;
}
RecvBuffer = LxtAlloc(LXT_TTYS_LARGE_BUFFER_SIZE);
if (RecvBuffer == NULL)
{
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
memset(RecvBuffer, 0, LXT_TTYS_LARGE_BUFFER_SIZE);
//
// Send and recv the data.
//
LxtCheckErrno(ChildPid = fork());
if (ChildPid == 0)
{
for (BytesTotal = 0; BytesTotal < LXT_TTYS_LARGE_BUFFER_SIZE; BytesTotal += BytesWritten)
{
BytesWritten = write(FdWrite, &SendBuffer[BytesTotal], LXT_TTYS_LARGE_BUFFER_SIZE - BytesTotal);
if (BytesWritten == -1)
{
if ((errno == EAGAIN) || (errno == EINTR))
{
BytesWritten = 0;
continue;
}
Result = LXT_RESULT_FAILURE;
LxtLogError("Write failed with %d", errno);
goto ErrorExit;
}
}
_exit(0);
}
for (BytesTotal = 0; BytesTotal < LXT_TTYS_LARGE_BUFFER_SIZE; BytesTotal += BytesRead)
{
BytesRead = read(FdRead, &RecvBuffer[BytesTotal], LXT_TTYS_LARGE_BUFFER_SIZE - BytesTotal);
if (BytesRead == -1)
{
if ((errno == EAGAIN) || (errno == EINTR))
{
BytesRead = 0;
continue;
}
Result = LXT_RESULT_FAILURE;
LxtLogError("Read failed with %d", errno);
goto ErrorExit;
}
}
LxtWaitPidPoll(ChildPid, 0);
for (Index = 0; Index < LXT_TTYS_LARGE_BUFFER_SIZE; ++Index)
{
if (RecvBuffer[Index] != (char)Index)
{
Result = LXT_RESULT_FAILURE;
LxtLogError("Mismatch at index %d: %d != %d", Index, (int)(RecvBuffer[Index]), (int)((char)Index));
goto ErrorExit;
}
}
Result = 0;
ErrorExit:
if (ChildPid == 0)
{
_exit(Result);
}
if (RecvBuffer != NULL)
{
LxtFree(RecvBuffer);
}
if (SendBuffer != NULL)
{
LxtFree(SendBuffer);
}
return Result;
}
int TtysWriteReadTermios(PLXT_ARGS Args, int FdRead, int FdWrite)
/*++
--*/
{
struct termios FdReadTermios;
int Fds[2];
struct termios FdWriteTermios;
int Index;
struct termios Termios;
int Result;
//
// Set the termios structure for transferring raw data.
//
Fds[0] = FdRead;
Fds[1] = FdWrite;
for (Index = 0; Index < LXT_COUNT_OF(Fds); ++Index)
{
LxtCheckErrno(tcgetattr(Fds[Index], &Termios));
Termios.c_iflag = 0;
Termios.c_oflag = 0;
Termios.c_cflag = B115200 | CREAD | CS8;
Termios.c_lflag = 0;
LxtCheckErrno(tcsetattr(Fds[Index], TCSANOW, &Termios));
}
memset(&FdReadTermios, 0, sizeof(FdReadTermios));
LxtCheckErrno(tcgetattr(FdRead, &FdReadTermios));
memset(&FdWriteTermios, 0, sizeof(FdWriteTermios));
LxtCheckErrno(tcgetattr(FdWrite, &FdWriteTermios));
LxtCheckMemoryEqual(&FdReadTermios, &FdWriteTermios, sizeof(FdWriteTermios));
Result = 0;
ErrorExit:
return Result;
}
int TtysWriteRead(PLXT_ARGS Args)
/*++
--*/
{
int BytesWritten;
dev_t Device;
int FdRead;
int FdWrite;
char Path[32];
int Result;
FdRead = -1;
FdWrite = -1;
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
LxtCheckErrno(FdRead = open(LXT_TTYS_DEFAULT, O_RDWR, 0));
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT2_MINOR);
mknod(LXT_TTYS_DEFAULT2, LXT_TTYS_DEV_MODE, Device);
LxtCheckErrno(FdWrite = open(LXT_TTYS_DEFAULT2, O_RDWR, 0));
LxtCheckResult(TtysWriteReadTermios(Args, FdRead, FdWrite));
//
// Transfer data with blocking IO
//
LxtCheckResult(TtysWriteReadTransfer(Args, FdRead, FdWrite));
//
// Transfer again with non-blocking IO.
//
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (FdRead != -1)
{
LxtClose(FdRead);
}
if (FdWrite != -1)
{
LxtClose(FdWrite);
}
return Result;
}
int TtysModemIoctls(PLXT_ARGS Args)
/*++
--*/
{
dev_t Device;
int Fd;
int ModemSettings;
int ModemSettingsOrig;
int Result;
struct termios Termios;
struct termios TermiosOrig;
Fd = -1;
ModemSettingsOrig = -1;
Result = LXT_RESULT_FAILURE;
//
// Check the default modem settings
//
Device = makedev(LXT_TTYS_DEV_MAJOR, LXT_TTYS_DEFAULT_MINOR);
mknod(LXT_TTYS_DEFAULT, LXT_TTYS_DEV_MODE, Device);
Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0);
if (Fd == -1)
{
if (errno == EIO)
{
LxtLogInfo("Skipping test %d", errno);
Result = LXT_RESULT_SUCCESS;
}
else
{
LxtLogError("Unexpected error %d", errno);
}
goto ErrorExit;
}
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettingsOrig));
LxtLogInfo("ModemSettingsOrig: %d", ModemSettingsOrig);
ModemSettings = ModemSettingsOrig;
LxtCheckResult(ioctl(Fd, TIOCMSET, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckEqual(ModemSettings, ModemSettingsOrig, "%d");
//
// Check that invalid settings are ignored
//
ModemSettings = -1;
LxtCheckResult(ioctl(Fd, TIOCMSET, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckNotEqual(ModemSettings, ModemSettingsOrig, "%d");
ModemSettings = -1;
LxtCheckResult(ioctl(Fd, TIOCMBIC, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckEqual(ModemSettings, 0, "%d");
ModemSettings = -1;
LxtCheckResult(ioctl(Fd, TIOCMBIS, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckNotEqual(ModemSettings, ModemSettingsOrig, "%d");
//
// Recheck the settings after closing and reopening.
//
LxtClose(Fd);
Fd = -1;
LxtCheckErrno(Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckNotEqual(ModemSettings, ModemSettingsOrig, "%d");
//
// Check DTR
//
// N.B. Some serial drivers start up with DTR on native Linux.
//
ModemSettings = ModemSettingsOrig & ~TIOCM_DTR;
LxtCheckResult(ioctl(Fd, TIOCMSET, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckEqual(ModemSettings, ModemSettingsOrig & ~TIOCM_DTR, "%d");
LxtClose(Fd);
Fd = -1;
LxtCheckErrno(Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0));
ModemSettings = TIOCM_DTR;
LxtCheckResult(ioctl(Fd, TIOCMBIS, &ModemSettings));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckEqual(ModemSettings, ModemSettingsOrig | TIOCM_DTR, "%d");
LxtClose(Fd);
Fd = -1;
LxtCheckErrno(Fd = open(LXT_TTYS_DEFAULT, O_RDWR | O_NONBLOCK, 0));
LxtCheckResult(ioctl(Fd, TIOCMGET, &ModemSettings));
LxtCheckEqual(ModemSettings, ModemSettingsOrig | TIOCM_DTR, "%d");
//
// Check that changing RTS doesn't impact termios
//
LxtCheckErrno(tcgetattr(Fd, &TermiosOrig));
ModemSettings = TIOCM_RTS;
LxtCheckResult(ioctl(Fd, TIOCMBIS, &ModemSettings));
LxtCheckErrno(tcgetattr(Fd, &Termios));
LxtCheckMemoryEqual(&TermiosOrig, &Termios, sizeof(Termios));
ModemSettings = TIOCM_RTS;
LxtCheckResult(ioctl(Fd, TIOCMBIC, &ModemSettings));
LxtCheckErrno(tcgetattr(Fd, &Termios));
LxtCheckMemoryEqual(&TermiosOrig, &Termios, sizeof(Termios));
Result = LXT_RESULT_SUCCESS;
ErrorExit:
if (Fd != -1)
{
if (ModemSettingsOrig != -1)
{
LxtCheckResult(ioctl(Fd, TIOCMSET, &ModemSettingsOrig));
}
LxtClose(Fd);
}
return Result;
}