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) 左CTRL 01(HEX) 左SHIFT 02(HEX) 左ALT 04(HEX) 右CTRL 10(HEX) 右SHIFT 20(HEX) 右ALT 40(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 == 0 xE0 ) buf[0 ]+=0 x01; //0x40 is [CTRL]
if ( d == 0 xE1 ) buf[0 ]+=0 x02; //0x80 is [SHIFT]
if ( d == 0 xE2 ) buf[0 ]+=0 x04; //0xC0 is [ALT]
if ( d>=0 xE0 ) 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 == 0 xff )
{
//DEBUG Mode
uint8_t debug_buf[8 ] = { 0 };
int i=0 ;
while (1 ){
if ( softSerial.available() ){
//マスターからの命令
int key;
key = softSerial.read(); //命令受け取る
if ( key==0 xff ) 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 0 xE0:
buf[0 ]|=0 x01; //[Left-CTRL]
break ;
case 0 xE4:
buf[0 ]|=0 x10; //[Right-CTRL]
break ;
case 0 xE1:
buf[0 ]|=0 x02; //[Left-SHIFT]
break ;
case 0 xE5:
buf[0 ]|=0 x20; //[Right-SHIFT]
break ;
case 0 xE2:
buf[0 ]|=0 x04; //[Left-ALT]
break ;
case 0 xE6:
buf[0 ]|=0 x40; //[Right-ALT]
break ;
default :
buf[2 ]= d; //1個目のキー代入
ret = true ; //送信
break ;
}
return ret;
}
これをArduinoに書込むことで、HID USBキーボードの心臓部が出来上がった。
お次ぎはマスターPC側のソフトを作らねば。>
つづく
コメント
SundayGamerさん、こんにちは。
Arduinoの購入目的がコレだったので、思い通りに動くようになってホツっとしてます。( ´ ▽ ` )ノ
SundayGamerさんのArduinoも、目的のものが作れるといいですね。
投稿: じむ | 2013/02/20 08:18
すげー。
wktk。
投稿: Sunday Gamer | 2013/02/17 23:02