File:  [Isaki's NoNo m68k/m88k emulator] / nono / host / comdriver_stdio.cpp
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//

//
// シリアルポートの標準入出力ドライバ
//

// 標準入力はここで担当するが、
// 標準出力はログ出力と共用するため Logger が担当となっている。

#include "comdriver_stdio.h"
#include "hostcom.h"
#include "logger.h"

// コンストラクタ
COMDriverStdio::COMDriverStdio(HostDevice *hostdev_)
	: inherited(hostdev_, "stdio")
{
}

// デストラクタ
COMDriverStdio::~COMDriverStdio()
{
	hostdev->DelOuter(STDIN_FILENO);

	// 端末属性を元に戻す
	if (tc_changed) {
		tcsetattr(STDIN_FILENO, TCSANOW, &oldtc);
	}

	stdio_occupied = false;
}

// ドライバ初期化
bool
COMDriverStdio::InitDriver(bool startup)
{
	struct termios tc;

	if (stdio_occupied) {
		errmsg = "'stdio' is already in use by another hostcom-driver";
		putmsg(1, "%s", errmsg.c_str());
		return false;
	}

	// 現在の端末属性を取得
	tcgetattr(STDIN_FILENO, &oldtc);

	// 端末の設定を変更
	tc = oldtc;

	// 入力時の変換は無し
	tc.c_iflag |= ICRNL;

	tc.c_lflag &= ~ECHO;	// エコーオフ
	tc.c_lflag &= ~ICANON;	// 非カノニカルモード
	tc.c_lflag &= ~IEXTEN;	// DISCARD(^O)と LNEXT をオフ?
	tc.c_lflag &= ~ISIG;	// シグナルを生成しない
	tc.c_cc[VTIME] = 0;
	tc.c_cc[VMIN] = 1;

	if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0) {
		errmsg = string_format("tcsetattr: %s", strerror(errno));
		putmsg(1, "%s", errmsg.c_str());
		return false;
	}
	tc_changed = true;

	if (hostdev->AddOuter(STDIN_FILENO) < 0) {
		errmsg = string_format("AddOuter: %s", strerror(errno));
		putmsg(1, "%s", errmsg.c_str());
		return false;
	}

	stdio_occupied = true;
	return true;
}

// 外部への1バイト書き出し
void
COMDriverStdio::Write(uint32 data)
{
	char str[2];

	str[0] = (uint8)data;
	str[1] = '\0';
	logger->WriteStdout(str);
}

// 外部からの1バイト読み込み
int
COMDriverStdio::Read()
{
	uint8 buf[1];
	int r;

	r = read(STDIN_FILENO, buf, sizeof(buf));
	if (r < 0) {
		putmsg(0, "read: %s", strerror(errno));
		return NODATA;
	}
	if (r == 0) {
		return NODATA;
	}
	return buf[0];
}

// stdio を使えるのは同時に1人だけに限定する。
/*static*/ bool COMDriverStdio::stdio_occupied = false;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.