USB接続のキーボードでは、Nキーロールオーバーに対応していても、USB HIDの仕様上同時に認識できるキーの個数は6個までと言われているが、ゲームコントローラーではHIDを利用していても7ボタン以上の同時押しが可能である。キーボードでは本当に7キー以上の同時押しができないのか検証してみる。

HID Report Descriptor

HID Report Descriptorでホストとデバイス間でやりとりされるパケット構造を定義できる。

Arduinoで使用されるKeyboardクラスのDescriptorは以下の通りである。

arduino-libraries/Keyboard - github.com

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x06,        // Usage (Keyboard)
0xA1, 0x01,        // Collection (Application)
0x85, 0x02,        //   Report ID (2)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)

// ※1
0x19, 0xE0,        //   Usage Minimum (0xE0)
0x29, 0xE7,        //   Usage Maximum (0xE7)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x75, 0x01,        //   Report Size (1)
0x95, 0x08,        //   Report Count (8)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

// ※2
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)

// ※3
0x95, 0x06,        //   Report Count (6)
0x75, 0x08,        //   Report Size (8)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x73,        //   Logical Maximum (115)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0x00,        //   Usage Minimum (0x00)
0x29, 0x73,        //   Usage Maximum (0x73)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)

0xC0,              // End Collection

※1の箇所は、修飾キーで使用される。Report Size 1(bit), Report Count 8(個)で、 8 bits = 1 byte 分が修飾キー用に確保されている。対応するキーは決まっており LCtrl RCtrl LShift RShift LAlt RAlt LWindows RWindows である。それぞれの修飾キーのON/OFFが各bitに対応する。

※2の箇所は予約用 1 byte。

※3の箇所は、修飾キー以外のキーで使用される。Report Size 8(bits), Report Count 6(個)で、6 bytes が確保されている。キーが入力されている間、それぞれのキーに対応したHID Usage ID(8 bits)を送信する必要があるが、Report Sizeは6であるため、キーを6個までしか入力できない。

検証

上記のHID Report Descriptorを使用し、ArduinoをKeyboardデバイスとして認識させ、キーボードの同時押しが確認できるサイトにて確認すると、6キーまでしか同時押しが反応しないことを確認できる。

通常のUSB HID Descriptorでは6キーまでしか入力できない

ここで、※3のReport Countを増やしてみる。

// ※3
0x95, 0x1a,        //   Report Count (26) 6 -> 26に変更した
0x75, 0x08,        //   Report Size (8)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x73,        //   Logical Maximum (115)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0x00,        //   Usage Minimum (0x00)
0x29, 0x73,        //   Usage Maximum (0x73)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)

このHID Report Descriptorを使用し、同様にArduinoをKeyboardデバイスとして認識させ、確認を行うと、26キーの同時押しが反応したことを確認できた。

HID Report Descriptorを書き換えると26キーの同時押しが確認できる

以上より、キーボードデバイスとしてUSB HIDを利用しても、7キー以上の同時押しが可能である。

なぜUSBキーボードのReport Countが6なのか

この辺は全然わかってないが、boot protocolに対応する必要があるためらしい。boot protocolに対応していない場合は、BIOS等で利用できない場面が存在するようだ。

実際USBキーボードは6キーまでしか同時押しできないのか

最近のキーボードはUSB接続でも7キー以上の同時押しに対応しているキーボードが多いようにみえる。

LEOPOLD FC400R、東プレ REALFORCE R2、Razer Huntsman miniを所有しているが、これらのキーボードはUSB接続でも10キー以上の同時押しが可能であることを確認している。 こんな記事を書いておいて、6キー制限に困ったことは特にないのでした。

参考