キーボードLEDの情報を取得するの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
NumLock,CapsLock,ScrollLockのLEDを制御します。今回一番苦労したところです。「LEDは付けない」という人には不要と思うかもしれませんが、テンキーの切替のためNumLockの情報だけは必要です。今回使用したキーボードはテンキーはありませんが側面に数字が印刷されたキーがあり、NumLockの状態によりキーコードを塗り替える処理を追加します。

!!LEDの情報はどう扱うのか
HIDの仕様書等参考資料によると、LEDの制御はデバイス側で行うのではなく、あくまでもデバイス側は押されたキーをホスト(PC)に送るだけでキーロックの状態はホストから送られて来る、と記述されています。SetConfigurationというコントロールトランスファで、エンドポイント0に1バイトのデータ(キーロック情報:下位5ビット)が送られて来ます。

SETUPstage:SETUPDAT[0..7]は、
,データ位置,内容,値
,SETUPDAT[0],bmRequestType,(0x21)
,SETUPDAT[1],bmRequest,SET_REPORT(0x09)
,SETUPDAT[2-3],wValue,Report Type (0x02) Report ID(0x00)
,SETUPDAT[4-5],wIndex,Interface (0x00)
,SETUPDAT[6-7],wLength,Report Length (0x0004)

DATAstage:EP0BUF[0]は、
,ビット位置,Usageコード,対応するLED 
,0,$01,Num Lock 
,1,$02,Caps Lock 
,2,$03,Scroll Lock 
,3,$04,Compose 
,4,$05,Kana 

のようにホストからデータが送られて来ます。

!!取得の仕方
まず、dscr.a51にLED情報を得られるようにReportDscr(14行目と15行目の間)に書き加えます。
     db  95h, 05h  ;; REPORT_COUNT (5) LED out
     db  75h, 01h  ;; REPORT_SIZE (1)
     db  05h, 08h  ;; USAGE_PAGE (LEDs)
     db  19h, 01h  ;; USAGE_MINIMUM (Num Lock)
     db  29h, 05h  ;; USAGE_MAXIMUM (Kana)
     db  91h, 02h  ;; OUTPUT (Data,Var,Abs)
     db  95h, 01h  ;; REPORT_COUNT (1)
     db  75h, 03h  ;; REPORT_SIZE (3)
     db  91h, 01h  ;; OUTPUT (Cnst) LED report padding

SetConfigurationは、fw.cのメイン処理で捕捉され、bulkloop.cのDR_SetConfiguration(void)を呼び出しているのでこの中に処理を書きます。
 BOOL DR_SetConfiguration(void)   // Called when a Set Configuration command is received
 {
    Configuration = SETUPDAT[2];
    if(SETUPDAT[0] == 0x21 && SETUPDAT[3] == 0x02){ //キーロック情報(Num,Scrlk,Capslk)取得
       Test = 1;
       EP0BCH = 0; EP0BCL = 0;
    }
    return(TRUE);            // Handled by user code
 }
フラグ(Test)を立てておき、このフラグが立っているときエンドポイント0にデータが来たときはLEDの情報だと判断します。EP0BCをリセットしていますがこうしておかないとデータが来ないようです。

次に、エンドポイント0出力の割込みを有効にします。fw.cの割込みの設定しているところに、
   EA = 1;                  // Enable 8051 interrupts
   EPIE |= 0x02; //Enable EndPoint0 OUT interrupt. ←追加
のように追加します。そしてエンドポイント0出力の割込み処理ISR_Ep0out(void)に処理を書き加えます。
 void ISR_Ep0out(void)  interrupt 0
 {
    if(Test){ // キーロック情報(Num,Scrlk,Capslk)取得
        lock_led = EP0BUF[0];
        if(lock_led != lock_led_bak){
            //lock_led b0:Num. b1:Caps. b2:Scroll.
            //IOD.b4〜b6:LED出力用.0で点灯.下位4ビットに影響を与えない
            OED = (OED & 0x0F) | ((lock_led << 4) & 0xF0);
            lock_led_bak = lock_led;
        }
        Test = 0;
    }
    EZUSB_IRQ_CLEAR();
    EPIRQ = 0x02; //Ep0out request clear
 }
lock_ledにLEDの情報が取得され、Dポート(b4〜b6)に接続したLEDを制御します。

!!LEDの取り付け
http://star.gmobb.jp/koji/data/keyboard_LED.JPG
ぎりぎりのサイズでケースを作ってしまってスペースが無いため、超小型のフルカラーLEDを使用しました。判り難いので市販のものには絶対採用されない方法ですがかえって手作りには面白いと思います。

USBキーボードの製作へ戻る

!!関連リンク
http://mcn.oops.jp/wiki/index.php?USB%2F%BB%C5%CD%CD
----
{{comment}}