« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その2) | トップページ | 白ROMスマホは安価音楽プレイヤー。 »

【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3)

Arduinoで作ったUSBキーボードシミュレータ
お次は、シリアル信号を送る側(マスターPC)の作成で、会社で使うためにWindowsPCが対象。
んで手慣れたのC#を使った。

今回作成したArduinoには、Windowsよりシリアル(9600bps 8N1)でUSBキーボードのキーコード(※)を送る。

  • ※:【USBキーボードのキーコード表】(www.usb.orgの資料より抜粋)

    USB英語101のキー種+[SHIFT]
    04aA
    05bB
    06cC
    07dD
    08eE
    09fF
    0AgG
    0BhH
    0CII
    0DjJ
    0EkK
    0FlL
    10mM
    11nN
    12oO
    13pP
    14qQ
    15rR
    16sS
    17tT
    18uU
    19vV
    1AwW
    1BxX
    1CyY
    1DzZ
    1E1!
    1F2@
    203#
    214$
    225%
    236^
    247&
    258'
    269(
    270)
    28Enter
    29Esc
    2ABackspace
    2BTab
    2CSpace
    2D-_
    2E=+
    2F[{
    30]}
    31\|
    33;:
    34'
    35`~
    36,<
    37.>
    38/?
    3AF1
    3BF2
    3CF3
    3DF4
    3EF5
    3FF6
    40F7
    41F8
    42F9
    43F10
    44F11
    45F12
    46Print Screen
    47Scroll Lock
    48Pause
    49Insert
    4AHome
    4BPage Up
    4CDelete
    4DEnd
    4EPage Down
    4F
    50
    51
    52
    53NumLock
    5410Key[/]
    5510Key[*]
    5610Key[-]
    5710Key[+]
    5810Key[Enter]
    5910Key[1]
    5A10Key[2]
    5B10Key[3]
    5C10Key[4]
    5D10Key[5]
    5E10Key[6]
    5F10Key[7]
    6010Key[8]
    6110Key[9]
    6210Key[0]
    6310Key[.]
    6510Key[App]
    6610Key[Power]
    6710Key[=]
    68F13
    69F14
    6AF15
    6BF16
    6CF17
    6DF18
    6eF19
    6FF20
    70F21
    71F22
    72F23
    73F24
    74Execute
    75Help
    76Menu
    77Select
    78Stop
    79Again
    7AUndo
    7BCut
    7CCopy
    7DPaste
    7EFind
    7FMute
    80VolumeUp
    81VolumeDown
    82Locking CapsLock
    83Locking NumLock
    84Locking ScrollLock



    E0Left-Ctrl
    E1Left-Shift
    E2Left-Alt
    E3Left-Windows
    E4Right-Ctrl
    E5Right-Shift
    E6Right-Alt
    E7Right-Windows



■実行させてみる

操作としては
  1. COMポートの接続
  2. USBキーボードコードの入力。そして送信

だけ。
【一応C#の方も以下にリストを載っけてみる。】

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports; //port
namespace Serial_USBkeyboard
{
public partial class Form1 : Form
{
//デリゲート宣言
private delegate void Delegate_RcvDataToTextBox(string data);
//コンストラクタ
public Form1()
{
InitializeComponent(); //お約束
//シリアル情報を入手
string[] ports = SerialPort.GetPortNames();
foreach (string com in ports)
{
comboBox1.Items.Add(com); //リストに追加
}
}
//シリアル応答用のテキストボックスへの書込み
private void Append_TextBox(string data)
{
//! 受信データをテキストボックスの最後に追記する.
if (data != null)
{
textBox2.AppendText(data);
}
}
//シリアル受信割り込み処理
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//受信割り込み
//シリアル受信→テキスト表示
try
{
//! 受信データを読み込む.
string data = serialPort1.ReadExisting();
//! 受信したデータをテキストボックスに書き込む.
Invoke(new Delegate_RcvDataToTextBox(Append_TextBox), new Object[] { data });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//シリアル・バッファ送信
private void send_bytes(byte[] buf)
{
if (serialPort1.IsOpen == false)
{
MessageBox.Show("Port don't Open");
return;
}
int i = 0;
foreach (byte b in buf)
{
serialPort1.Write(buf, i, 1); //1Byte send
i++; //Shift
System.Threading.Thread.Sleep(80); //Wait
}
}
//キーコード文字列の送信
private void send_string(string s)
{
//送信ボタン押下
if (String.IsNullOrEmpty(s)) return;
string[] data = s.Split(','); //文字列','でバラす
byte[] buf = new byte[data.Length]; //同容量分バッファキープ
int i = 0;
foreach (string d in data)
{
if (d.Length != 2) continue;
buf[i] = Convert.ToByte(d, 16); //文字をHEX数字として変換
++i; //
}
send_bytes(buf);
}
//[接続]ボタン押下処理
private void button1_Click(object sender, EventArgs e)
{
//[接続]ボタン押下
if (String.IsNullOrEmpty(comboBox1.Text)) return;
serialPort1.PortName = comboBox1.Text;
serialPort1.Open(); //シリアルオープン
if (serialPort1.IsOpen) //ポートチェック
{
groupBox2.Enabled = true; //開けた→送信欄許可
}
else
{
MessageBox.Show("Port(" + comboBox1.Text + ")が開けませんでした。");
}
}
//[送信]ボタン押下処理
private void button2_Click(object sender, EventArgs e)
{
send_string(textBox1.Text); //入力した文字列送信
}
//テキストで[Enter]押し
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter) //[改行]チェック
{
button2_Click(sender, e); //送信ボタンと同じ処理へ
}
}
//[キーリリース]送信
private void button3_Click(object sender, EventArgs e)
{
send_string("ff,ff"); //オール0送信
}
//Macのスクリーンショット([SHIFT]+[Command]+'3')
private void button4_Click(object sender, EventArgs e)
{
send_string("ff,02,00,e7,00,ff"); //[SHIFT]+[Command]
send_string("ff,02,00,e7,20,ff"); //[SHIFT]+[Command]+'3'
send_string("ff,ff"); //Key Release
}
//Macの[全角/半角]切替
private void button5_Click(object sender, EventArgs e)
{
send_string("ff,00,00,e7,00,ff"); //[Command]
send_string("ff,00,00,e7,2c,ff"); //[Command]+' '
send_string("ff,00,00,e7,00,ff"); //[Command]
send_string("ff,ff"); //Key Release
}
//[PageUp]キー押下
private void button7_Click(object sender, EventArgs e)
{
send_string("4b");
}
//[PageDown]キー押下
private void button8_Click(object sender, EventArgs e)
{
send_string("4e");
}
//[Windows]キー押下
private void button6_Click(object sender, EventArgs e)
{
send_string("e7");
}
}
}

  • 'a'というキーを押したことにするなら入力欄にキーコード"04"と入れて送信。
  • スレーブPCにMacを対象として接続しているなら、ボリュームを上げたいときには、キーコード"80"を入力して送信。
  • 'A'であれば、[SHIFT]+'a'ということになるので、まずはSHIFTの"e0"
    ','を挟んで、'a'である"04"と入力して"e0,04"として送信する。
  • すると、スレーブ側のPCに'A'(=[SHIFT]+'a')とキーを押したことが伝えられる。
  • これらArduinoの動きはシリアル通信でマスターPC側にフィードバックしてくるようにした。
    これで実際にマスターPC側に送られたかどうかわかるようにした。
  • またベタに8バイト送れるように、前後を"FF"で囲んで入力すれば良いようにした。
    先ほどの'A'ならば、"FF,02,00,04,FF"と入力。
  • これを利用するとMacでスクリーンショットを取る("[Command]+[SHIFT]+[3]")等の複数キーによる動作も…
      "FF,00,00,e7,00,ff""FF,00,00,e7,20,ff""FF,FF"
    てな文字列を順次に送ると行える。
    ([Command]キーは[Windows]キーと同じなので、"e3"または"e7"
  • 後はこれらコードを適当にテキストフィルにまとめて、それを読み込ませて、任意の時間間隔で送信するようにすれば、最近流行(?)の「PC遠隔操作」ならぬ、「PC近隣操作」のできあがり〜♪。w


現在の構成の欠点は、めくら撃ちでキーを打つため、HDDのアクセスが遅くて動作に遅延が生じた場合、それ以降の動作がメタメタになってしまうこと。
そのため、キーの送信間隔を十分に取るようにした。

ということで、この治具を使った会社のWindowsPC(30台分)の設定自動検査も終わって、開発終了!。

| |

« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その2) | トップページ | 白ROMスマホは安価音楽プレイヤー。 »

コメント

pchanさん、コメントありがとうございます。
Leonardoは、私が買ったUno R3より、安いですよね。
搭載しているチップ構成が違うので値段も違っております。

実際自分でLeonardoを購入して試していないので、胸を張って「できますよ」とは言えないのですが…と前置きをして。
LeonardoでもUSBキーボードやらマウスの動作が出来るような情報はネットでも上がっていますね。

ただ、最初はトラブることも考慮してデバッグ等の機能も設けておいた方が良いと思いますので、Uno R3の方が良いと思いますよ。

投稿: じむ | 2013/10/08 00:33

Arduinoにキーボードのふりをさせたいと思い調べていたところこのブログにたどり着きました.

Arduino Leonardoではもともとキーボードやマウスとして振る舞えるような機能が付いているようなのですが,Leonardoでも今回のような動作は可能なのでしょうか?

Arduinoをこれから始めようと思っているのですが,どれを購入すればいいのか迷っています.

よろしくお願いします.

投稿: pchan | 2013/10/06 23:45

コメントありがとうございます。

質問にお答えします。
確かに、「同時押しなら簡略出来るのでは?」というご意見、最もだと思います。

“キー入力の仕様”ってことになりますかね。
キーの入力順番も見ているようです。
なので、瞬時の同時押しでも、スローモーションっぽく逐次キーデータを送らないと、向こうが受け付けてくれないのでした。
(体験談)

こんな回答でご理解いただければ幸いです。

投稿: じむ | 2013/05/06 21:59

素晴らしい記事をありがとう。

早速ですが質問をさせて下さい。

>スクリーンショットを取る("[Command]+[SHIFT]+[3]")等の複数キーによる動作も…"FF,00,00,e7,00,ff"、"FF,00,00,e7,20,ff"、"FF,FF"

と有りますがどうして "FF,00,00,e7,20,ff"、"FF,FF" の二つではいけないのでしょうか?

C#のソースも

> send_string("ff,00,00,e7,00,ff"); //[Command]
> send_string("ff,00,00,e7,2c,ff"); //[Command]+' '
> send_string("ff,00,00,e7,00,ff"); //[Command]
> send_string("ff,ff"); //Key Release

この部分が

send_string("ff,00,00,e7,2c,ff"); //[Command]+' '
send_string("ff,ff"); //Key Release

の二行でNGな訳を教えて頂けないでしょうか?

どうぞよろしくお願いします。

投稿: | 2013/05/06 13:34

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック


この記事へのトラックバック一覧です: 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3):

« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その2) | トップページ | 白ROMスマホは安価音楽プレイヤー。 »