OSを自作してみる3 ~キーボード入力~



文字を入力して出力する機能を付けてみた。

※過去回の記事とソースコードは下記から入手できる
https://github.com/Shadow5523/osdev/blob/master/README.md
また、ここで使用するコードはGitHubからダウンロードできる。
https://github.com/Shadow5523/osdev/releases/tag/version0.2.0

文字を入力する機能を付けただけで、まだファンクションキーなどには機能を割り当てていない。
最低限エンターキーとバックスペースキー、タブキーのみ実装した。

キーボードからCPUに送られてくるスキャンコード呼ばれるコードをinb()関数で取得して、
あらかじめ定義したkeytable配列に格納してある文字定数とマッピング(スキャンコードセットという)させて画面へ出力させるシンプルな作りだ。
スキャンコードにはキーを押されたときに送信されるコード(メイクコード)とキーが離されたときに送信されるコード(ブレイクコード)2つがある。

キーボードの入力はUSBからPS/2エミュレーションを使用して入力する。(なので、あんまり古過ぎるPCでは入力することができない)

スキャンコードはセットが3種類あって、今回対応させたのは(というかqemuのデフォルトが)「スキャンコードセット1」。現在の主流は「スキャンコードセット2」らしく。「スキャンコードセット3」はPS2キーボードの拡張として設定されているらしいがほとんど使われていない。

ただVMWareやVirtualBoxなどの仮想マシンはスキャンコードを確認するコマンドや変更するコマンドが削除されていたりして「スキャンコードセット1」から変更することができなかった。自宅にあったノートPC dell latitude e4310やデスクトップPCなどもスキャンコードセットの確認や変更ができなかったので、もしかしたら最近のマシンは変更ができないのかもしれない。

1.まずはキー入力で得られたスキャンコードをアルファベット等の文字へ置き換えたり、実際にスキャンコードを取得するプログラムkeyboard.cとkeyboard.hを作成。
//keyboard.h

 

//keyboard.c

 

2.I/Oポートからデータを取得したり送ったりするプログラムinb_outb.hを作成する。
//inb_outb.h

 

inb()関数は指定したI/Oポートからデータを取ってきたりし、outb()関数で指定したI/Oポートへデータを送る。キーボードからデータを取ってくる場合は0x60のポートから取得する。

3.kernel.hへ新しく作製したkeyboard.hとinb_outb.hをインクルードするようにコードを追加する。
//kernel.h

 

4.kernel.cを以下のように編集
//kernel.c

 

terminal.hとterminal.cへバックスペース、エンターなどのキーが来たときの挙動を追加する。
//terminal.c

 

//terminal.h

 

5.Makefileに以下のように編集
//Makefile

 

6.makeコマンドでビルドし、qemuで前回同様実行するとキー入力ができるようになっている。(VMWare/実機(dell latitude e4310)ではなぜか連続キー入力ができないが、あとで割り込み経由での入力へ切り替えを行うので問題なし)

しかし実際に動いているOSはこのようなやり方でのキーボード入力の方法ではなく、割り込みを使ったキー入力が一般的である。
そのためにはGDT/IDTのと呼ばれるものを初期化して割り込みをちゃんとできるようにしなければならないので次回行っていきたいと思う。

Leave a Reply

Your email address will not be published. Required fields are marked *