« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その1) | トップページ | 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3) »

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

ArduinoUNOでの16U2に書込む"Arduino-keyboard-0.3.hex"は、偉いもので相方である328P側にとっては単なる通信シリアル相手で、16U2が「USBキーボード・モード」であっても「シリアル通信モード」であっても同じプログラムでかまわないようになっていた。


よく考えられているのぉ。

Wikipediaの「スキャンコード」の項で実際にデータとして用いるUSBのキーコードについてお勉強。
φ(・ω・ )

  • ほ〜8バイト送ることで、そのキーを押したことになるのか。
  • これだけだと押っぱなしなので、再度“全て0の値の8バイト”を送ることで、そのキーを離したことになるのね。
  • さらに詳細を追うと…この8バイト(buf[0]〜[7]とする)の内、1個のキーを送るなら使うのは[0]と[2]があればいいわけか。
  • buf[0]にはALTやらCTRLやらSHIFTの装飾コードを代入すると。
    内容値(HEX)
    左CTRL01(HEX)
    左SHIFT02(HEX)
    左ALT04(HEX)
    右CTRL10(HEX)
    右SHIFT20(HEX)
    右ALT40(HEX)

  • んで、buf[2]には実際のキーコードを代入っと。
まぁ大雑把にそんな流れであった。

そんなことをふまえてArduinoのプログラムを作成。
前回でPC同士のシリアル通信処理を改良して、HID USBキーボード向けに作り替えた。
//Arduino USB Keyboard simulator
//Using "Arduino-keyboard-0.3.hex" for ATMega 16U2
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2,3); //SoftwareSerial(rxPin, txPin)

//Grobal value
uint8_t buf[8] = { 0 }; /* Keyboard report buffer 8Byte */

//【初期設定】
void setup()
{
//Hardware Serial PD0:RX,PD1:TX
Serial.begin(9600); //bitrate
//Software Serial port PD2:RX,PD3:TX
softSerial.begin(9600); //bitrate
softSerial.println("SoftwareSerial"); //Initial test word
delay(200);
}

//【ループ処理】
void loop()
{
//マスターからの命令待ち
if( softSerial.available() ){
//マスターからの命令
int key;
key = softSerial.read(); //命令受け取る
//どんな命令か、チェックする。
if( true == decode_keycode(key) )
{
//使えるデータならマスターにデータのfeedback
softSerial.print( "Key(0x" );
softSerial.print( key,HEX );
softSerial.print( ")..." );
softSerial.print( "[0]=0x" );
softSerial.print( buf[0],HEX );
softSerial.print( ",[2]=0x" );
softSerial.println( buf[2],HEX );
//16U2側にHID USBキーボードデータ(8バイト)送信
Serial.write(buf,8); //send 8byte data to serial port
releasekey(); //send 8byte(all null data) to serial port
}
}
}

//【キーを放す】
void releasekey()
{
buf[0] = 0; //[0] clear
buf[2] = 0; //[2] clear
//Send Buffer:8Byte([0]---[7])
Serial.write(buf, 8); // Release key
}

//【受け取った命令のデコード】
bool decode_keycode(int d)
{
// Attribute Code
// keycode [0].... 0:LeftCTRL, 1:LeftSHIFT, 2:LeftALT, 3:LeftGUI
// 4:RightCTRL,5:RightSHIFT,6:RightALT,7:RightGUI
// 0xE0〜0xFF....Attribute
if( d == 0xE0 ) buf[0]+=0x01; //0x40 is [CTRL]
if( d == 0xE1 ) buf[0]+=0x02; //0x80 is [SHIFT]
if( d == 0xE2 ) buf[0]+=0x04; //0xC0 is [ALT]
if( d>=0xE0 ) return false; //装飾データ→false
else buf[2]= d; //キーデータとしてそのまま採用→true
return true;
}


■【2013/2/24:追記】
前回のArduinoのスケッチは「1個のキー」にしか対応していなかったので、新たに「複数キーの同時押し」にも対応できるように、内容に変更した。
んで出来たのがこれ_。
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2,3); //SoftwareSerial(rxPin, txPin)
//Grobal value
uint8_t buf[8] = { 0 }; /* Keyboard report buffer 8Byte */
//【初期設定】
void setup()
{
//Hardware Serial PD0:RX,PD1:TX
Serial.begin(9600); //bitrate
//Software Serial port PD2:RX,PD3:TX
softSerial.begin(9600); //bitrate
softSerial.println("SoftwareSerial"); //Initial test word
delay(200);
}
//【ループ処理】
void loop()
{
//マスターからの命令待ち
if( softSerial.available() ){
//マスターからの命令
int key;
key = softSerial.read(); //命令受け取る
if( key == 0xff )
{
//DEBUG Mode
uint8_t debug_buf[8] = { 0 };
int i=0;
while(1){
if( softSerial.available() ){
//マスターからの命令
int key;
key = softSerial.read(); //命令受け取る
if( key==0xff ) break;
debug_buf[i]=key;
++i;
if( i>7 ) break;
}
}
for( i=0;i<8;++i )
{
softSerial.print(debug_buf[i],HEX); //feedback
softSerial.print("-");
}
Serial.write(debug_buf,8); //send 8byte data to serial port
softSerial.println("");
delay(100);
}
else
{
//どんな命令か、チェックする。
if( true == decode_keycode(key) )
{
//使えるデータならマスターにデータのfeedback
softSerial.print( "[0]=0x" );
softSerial.print( buf[0],HEX );
softSerial.print( ",[2]=0x" );
softSerial.print( buf[2],HEX );
if( buf[3]!=0 )
{
softSerial.print( ",[3]=0x" );
softSerial.print( buf[3],HEX );
}
softSerial.println("");

//16U2側にHID USBキーボードデータ(8バイト)送信
Serial.write(buf,8); //send 8byte data to serial port
delay(100);
releasekey(); //send 8byte(all clear) to serial port
}
}
}
}
//【キーを放す】
void releasekey()
{
//Send Buffer:8Byte([0]---[7])
buf[0] = 0; //[0] clear
buf[1] = 0; //[1] clear
buf[2] = 0; //[2] clear
buf[3] = 0; //[3] clear
buf[4] = 0; //[4] clear
buf[5] = 0; //[5] clear
buf[6] = 0; //[6] clear
buf[7] = 0; //[7] clear
Serial.write(buf,8); //Release
}
//【受け取った命令のデコード】
bool decode_keycode(int d)
{
bool ret=false; //非送信
// Attribute Code
// keycode [0].... 0:LeftCTRL, 1:LeftSHIFT, 2:LeftALT, 3:LeftGUI
// 4:RightCTRL,5:RightSHIFT,6:RightALT,7:RightGUI
// 0xE*....Attribute keycode
switch( d )
{
case 0xE0:
buf[0]|=0x01; //[Left-CTRL]
break;
case 0xE4:
buf[0]|=0x10; //[Right-CTRL]
break;
case 0xE1:
buf[0]|=0x02; //[Left-SHIFT]
break;
case 0xE5:
buf[0]|=0x20; //[Right-SHIFT]
break;
case 0xE2:
buf[0]|=0x04; //[Left-ALT]
break;
case 0xE6:
buf[0]|=0x40; //[Right-ALT]
break;
default:
buf[2]= d; //1個目のキー代入
ret = true; //送信
break;
}
return ret;
}

これをArduinoに書込むことで、HID USBキーボードの心臓部が出来上がった。
お次ぎはマスターPC側のソフトを作らねば。>つづく

| |

« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その1) | トップページ | 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3) »

コメント

SundayGamerさん、こんにちは。

Arduinoの購入目的がコレだったので、思い通りに動くようになってホツっとしてます。( ´ ▽ ` )ノ
SundayGamerさんのArduinoも、目的のものが作れるといいですね。

投稿: じむ | 2013/02/20 08:18

すげー。
wktk。

投稿: Sunday Gamer | 2013/02/17 23:02

コメントを書く



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


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



トラックバック


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

» 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3) [じむの(とりあえず)やってみたの巻]
Arduinoで作ったUSBキーボードシミュレータ。 お次は、シリアル信号を送る [続きを読む]

受信: 2013/02/24 18:46

« 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その1) | トップページ | 【ArduinoUNO】HID USBキーボードシミュレータ?を作ってみた。(その3) »