動機

自宅では、 MacBookPro をクラムシェル状態で利用し、キーボードはHHKB。

快適ではあるが、電源 or EjectボタンのないHHKBで、sleepモードにするのがめんどくさい。

訂正 Fn + F で Eject

いままでは、メニューから選択していた。

アプリでHHKB のキーマップを変えるのもありだが、いっそ su120 で便利なsleepキーのついた小さなキーボードを作るのもありか?

と思っていたが、よく考えると、そうじゃない。 猫がマウスをいじってsleepから覚めることもあるし、ベッドからsleep操作したい。

機種選定

ならば、BLEのキーボードを作る。

Pro Micro(ATmega32U4 5V 16MHz)  は、BLEの機能がついていないので、ESP32 にボタンやLEDのついた Atom Liteを利用する。

BLE Keyboard のライブラリsetup

github で公開されているESP32用Arudinoのライブラリをdownload

展開したファイルをArduino のライブラリ環境に保存。 macなら $HOME/Documents/Arduino/libraries/ESP32-BLE-Keyboard/

Program

mac の sleep操作 は、以下の3種類

  • 電源ボタンを1.5秒
  • option + command + 電源ボタン
  • option + command + メディア取り出しキー

参考

さて、ESP32-BLE-Keyboard のドライバで command や 電源ボタンを入力するのにはどうしたらいいか?

サンプルコードから、

c
bleKeyboard.press(KEY_LEFT_CTRL);

この KEY_LEFT_CTRL にあたる部分に以下のように割り当てればいいことはわかる。

  • option = KEY_LEFT_ALT
  • command = KEY_LEFT_GUI

でも電源ボタンは?

どうやら、USB HIDに規定されるHID Usage ID がわかればよいことがわかった。Microsoftの USB HID to PS/2 Scan Code Translation Table という資料が役にたった。

以下、クリックするとPDF。

PS/2 部分は不要だが、 Keyboard Power という項目の HID Usage ID が、 0x66 だとわかる。

つまり、こんなコードでよいはず。

c
KeyReport keyReport;

//
// Power + Left Control + Command = sleep
//

// press
memset(&keyReport, 0, sizeof(keyReport));
keyReport.keys[0] = 0x66;     // Power
keyReport.keys[1] = 0xE0;     // Left Control
keyReport.keys[2] = 0xE3;     // Left GUI(Command)
bleKeyboard.sendReport(&keyReport);

AtomLiteのボタンを押すと、LEDを光らせ、BLE接続先のMacにsleepキーセットを送るプログラム

atom_sleep_keyboard.ino · Gistcpp
#include "M5Atom.h"
#include <BleKeyboard.h>

BleKeyboard bleKeyboard("Atom Keyboard");

void setup()
{
    Serial.begin(115200);
    
    
    M5.begin(true, false, true);
    M5.dis.drawpix(0, 0xf00000);  // init red

    Serial.println("Starting BLE work!");
    delay(20);
    bleKeyboard.begin();
    delay(20);

    M5.dis.drawpix(0, 0x100000);    // dark green
}

void loop()
{
    if (M5.Btn.wasPressed()) {
        M5.dis.drawpix(0, 0x0000f0);    // blue
        
        if (bleKeyboard.isConnected()) {
            KeyReport keyReport;

            //
            // Power + Left Control + Command = sleep
            //

            // press
            memset(&keyReport, 0, sizeof(keyReport));
            keyReport.keys[0] = 0x66;     // Power
            keyReport.keys[1] = 0xE0;     // Left Control
            keyReport.keys[2] = 0xE3;     // Left GUI(Command)
            bleKeyboard.sendReport(&keyReport);
            
            // keep press
            delay(500);

            // release
            memset(&keyReport, 0, sizeof(keyReport));
            bleKeyboard.sendReport(&keyReport);
        }

        M5.dis.drawpix(0, 0x100000);    // dark green
    }
    delay(100);
    M5.update();
}

Mac のKeyboard認証

プロフラムの4行目で BLE Keyboard 名を設定している。

c
BleKeyboard bleKeyboard("Atom Keyboard");

AtomLiteにプログラムを書き込み後、MacからBlueTooth機器を探す。

Connect すれば、OK