【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3)
Arduinoで作ったUSBキーボードシミュレータ。
お次は、シリアル信号を送る側(マスターPC)の作成で、会社で使うためにWindowsPCが対象。
んで手慣れたのC#を使った。
今回作成したArduinoには、Windowsよりシリアル(9600bps 8N1)でUSBキーボードのキーコード(※)を送る。
- ※:【USBキーボードのキーコード表】(www.usb.orgの資料より抜粋)
USB 英語101のキー種 +[SHIFT] 04 a A 05 b B 06 c C 07 d D 08 e E 09 f F 0A g G 0B h H 0C I I 0D j J 0E k K 0F l L 10 m M 11 n N 12 o O 13 p P 14 q Q 15 r R 16 s S 17 t T 18 u U 19 v V 1A w W 1B x X 1C y Y 1D z Z 1E 1 ! 1F 2 @ 20 3 # 21 4 $ 22 5 % 23 6 ^ 24 7 & 25 8 ' 26 9 ( 27 0 ) 28 Enter 29 Esc 2A Backspace 2B Tab 2C Space 2D - _ 2E = + 2F [ { 30 ] } 31 \ | 33 ; : 34 ' ” 35 ` ~ 36 , < 37 . > 38 / ? 3A F1 3B F2 3C F3 3D F4 3E F5 3F F6 40 F7 41 F8 42 F9 43 F10 44 F11 45 F12 46 Print Screen 47 Scroll Lock 48 Pause 49 Insert 4A Home 4B Page Up 4C Delete 4D End 4E Page Down 4F → 50 ← 51 ↓ 52 ↑ 53 NumLock 54 10Key[/] 55 10Key[*] 56 10Key[-] 57 10Key[+] 58 10Key[Enter] 59 10Key[1] 5A 10Key[2] 5B 10Key[3] 5C 10Key[4] 5D 10Key[5] 5E 10Key[6] 5F 10Key[7] 60 10Key[8] 61 10Key[9] 62 10Key[0] 63 10Key[.] 65 10Key[App] 66 10Key[Power] 67 10Key[=] 68 F13 69 F14 6A F15 6B F16 6C F17 6D F18 6e F19 6F F20 70 F21 71 F22 72 F23 73 F24 74 Execute 75 Help 76 Menu 77 Select 78 Stop 79 Again 7A Undo 7B Cut 7C Copy 7D Paste 7E Find 7F Mute 80 VolumeUp 81 VolumeDown 82 Locking CapsLock 83 Locking NumLock 84 Locking ScrollLock E0 Left-Ctrl E1 Left-Shift E2 Left-Alt E3 Left-Windows E4 Right-Ctrl E5 Right-Shift E6 Right-Alt
E7 Right-Windows
■実行させてみる
操作としては
- COMポートの接続
- 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");
}
}
}
現在の構成の欠点は、めくら撃ちでキーを打つため、HDDのアクセスが遅くて動作に遅延が生じた場合、それ以降の動作がメタメタになってしまうこと。
そのため、キーの送信間隔を十分に取るようにした。ということで、この治具を使った会社のWindowsPC(30台分)の設定自動検査も終わって、開発終了!。
- COMポートの接続
| 固定リンク | 0
コメント
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