|
|
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;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.