Arduino로 키 컨버터 만들기

9291 단어 HIDUSBArduino
2021.4.30: 소스코드 수정(PC측에서 시리얼 접속하지 않으면 동작하지 않는 문제 수정)



참고로 한 것



[ htps : // 오키라쿠-카메라. 토키오/bぉg/? p=8193 ]

만드는 법


  • 키보드: Thinkpad keyboard with Tracpoint
  • 하드 : 참고와 함께
  • 소프트:참고로 한 것은 keyboard 뿐이었으므로 Arduino의 표준 라이브러리의 USBHIDBootKbdAndMouse 의 샘플을 기초로 구현(tracpoint가 사용하고 싶다!!)
  • 참고 : Aruduino 표준 라이브러리 키보드의 sendReport()private에서 public로 변경했습니다.

  • keybord_converter.ino
    /** 
     * KeyCodeConvert
     * original Keyboard Library must be modified.
     * in Keyboard.h, function "sendReport()" should be change to "public" from "private".
     */
    
    #include <hidboot.h>
    #include <usbhub.h>
    
    #include "Keyboard.h"
    #include "Mouse.h"
    
    // Satisfy IDE, which only needs to see the include statment in the ino.
    #ifdef dobogusinclude
    #include <spi4teensy3.h>
    #endif
    #include <SPI.h>
    
    // KeyReportのmodifiersのビット構成
    static const uint8_t MODIFIRE_LEFT_CONTROL = 0x01;
    static const uint8_t MODIFIRE_LEFT_SHIFT = 0x02;
    static const uint8_t MODIFIRE_LEFT_ALT = 0x04;
    static const uint8_t MODIFIRE_LEFT_GUI= 0x08;
    static const uint8_t MODIFIRE_RIGHT_CONTROL = 0x10;
    static const uint8_t MODIFIRE_RIGHT_SHIFT = 0x20;
    static const uint8_t MODIFIRE_RIGHT_ALT = 0x40;
    static const uint8_t MODIFIRE_RIGHT_GUI= 0x80;
    
    //#define DEBUG_PRINT
    
    class MouseRptParser : public MouseReportParser
    {
      protected:
        void OnMouseMove(MOUSEINFO *mi);
        void OnLeftButtonUp(MOUSEINFO *mi);
        void OnLeftButtonDown(MOUSEINFO *mi);
        void OnRightButtonUp(MOUSEINFO *mi);
        void OnRightButtonDown(MOUSEINFO *mi);
        void OnMiddleButtonUp(MOUSEINFO *mi);
        void OnMiddleButtonDown(MOUSEINFO *mi);
    };
    void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.print("dx=");
      Serial.print(mi->dX, DEC);
      Serial.print(" dy=");
      Serial.println(mi->dY, DEC);
    #else
      Mouse.move(mi->dX, mi->dY);
    #endif
    };
    void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("L Butt Up");
    #else
      Mouse.release(MOUSE_LEFT);
    #endif
    };
    void MouseRptParser::OnLeftButtonDown   (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("L Butt Dn");
    #else
      Mouse.press(MOUSE_LEFT);
    #endif
    };
    void MouseRptParser::OnRightButtonUp    (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("R Butt Up");
    #else
      Mouse.release(MOUSE_RIGHT);
    #endif
    };
    void MouseRptParser::OnRightButtonDown  (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("R Butt Dn");
    #else
      Mouse.press(MOUSE_RIGHT);
    #endif
    };
    void MouseRptParser::OnMiddleButtonUp   (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("M Butt Up");
    #else
      Mouse.release(MOUSE_MIDDLE);
    #endif
    };
    void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
    {
    #ifdef DEBUG_PRINT
      Serial.println("M Butt Dn");
    #else
      Mouse.press(MOUSE_MIDDLE);
    #endif
    };
    
    bool modifyKey(uint8_t* pKey, bool bDown);
    bool modifyModifier(uint8_t before, uint8_t after);
    void sendReport(KeyReport* report);
    
    class KbdRptParser : public KeyboardReportParser
    {
        void PrintKey(uint8_t mod, uint8_t key);
    
      protected:
        void OnControlKeysChanged(uint8_t before, uint8_t after);
        void OnKeyDown  (uint8_t mod, uint8_t key);
        void OnKeyUp    (uint8_t mod, uint8_t key);
    //    void OnKeyPressed(uint8_t key);
    };
    
    KeyReport keyReport;
    
    void sendReport(KeyReport* report)
    {
      Serial.print("== ");
      Serial.print(report->modifiers, HEX);
      Serial.print(":");
      Serial.print(report->keys[0], HEX);
      Serial.println(" ==");
    
      Keyboard.sendReport(report);
    }
    
    /**
     * 修飾キー変換
     * @note Controlの場合はCapsLockに変更
     * @param [in] MODIFIERKEYS before: 前回の修飾キー状態 
     * @param [in] MODIFIERKEYS after: 今回の修飾キー状態
     * @return bool : 修飾キー変換したかどうか
     */
    bool modifyModifier(MODIFIERKEYS before, MODIFIERKEYS after)
    {
      // Control->CAPSLOCK(0x39)
      if (before.bmLeftCtrl != after.bmLeftCtrl)
      {
        if (after.bmLeftCtrl)
        {
          Serial.println("CAPSLOCK DOWN");
          keyReport.keys[0] = 0x39;      
        }
        else
        {
          Serial.println("CAPSLOCK UP");
          keyReport.keys[0] = 0;      
        }
        sendReport(&keyReport);
        return true;
      }
    
      return false;
    }
    
    /**
     * キー変換
     * @param [in/out] uint8_t* pKey: キーコード
     * @param [in] bool bDown: 押下
     * @return bool : true キー変換実施, false modifierとして処理
     */
    bool modifyKey(uint8_t* pKey, bool bDown)
    {
      switch(*pKey) {
        case 0x29: // ESC(0x29)->半角/全角(0x35)
          *pKey = 0x35;
          break;
        case 0x35: // 半角/全角(0x35)->ESC(0x29)
          *pKey = 0x29;
          break;
        case 0x8A: // 変換(0x8A)->半角/全角(0x35)
          *pKey = 0x35;
          break;
        case 0x8B: // 無変換(0x8B)->半角/全角(0x35)
          *pKey = 0x35;
            break;
        case 0x39: // CAPSLOCK(0x39)->Control
        {
          KBDINFO* pKbdInfo;
          pKbdInfo = (KBDINFO*)&keyReport;
          if (bDown) 
          {
            pKbdInfo->bmLeftCtrl = 1;
            Serial.println("LeftCtrl down");      
          }
          else
          {
            pKbdInfo->bmLeftCtrl = 0;
            Serial.println("LeftCtrl up");      
          }
          return false;
        }
        default:
          break;
      }
    
      Serial.print("changed to ");
      Serial.println(*pKey, HEX);
    
      return true;  
    }
    
    void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
    {
      MODIFIERKEYS mod;
      *((uint8_t*)&mod) = m;
      Serial.print((mod.bmLeftCtrl   == 1) ? "C" : " ");
      Serial.print((mod.bmLeftShift  == 1) ? "S" : " ");
      Serial.print((mod.bmLeftAlt    == 1) ? "A" : " ");
      Serial.print((mod.bmLeftGUI    == 1) ? "G" : " ");
    
      Serial.print(" >");
      PrintHex<uint8_t>(key, 0x80);
      Serial.print("< ");
    
      Serial.print((mod.bmRightCtrl   == 1) ? "C" : " ");
      Serial.print((mod.bmRightShift  == 1) ? "S" : " ");
      Serial.print((mod.bmRightAlt    == 1) ? "A" : " ");
      Serial.println((mod.bmRightGUI    == 1) ? "G" : " ");
    };
    
    void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
    {
      // キー変換
      if (modifyKey(&key, true))
      {
        Serial.print("DN ");
        keyReport.keys[0] = key;
        PrintKey(keyReport.modifiers, key);
        sendReport(&keyReport);
    
    //  uint8_t c = OemToAscii(mod, key);
    //  if (c)
    //    OnKeyPressed(c);    
      }
    }
    
    void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
    {
      if (modifyKey(&key, false))
      {
        Serial.print("UP ");
        keyReport.keys[0] = 0;
        PrintKey(keyReport.modifiers, key);
        sendReport(&keyReport);  
      }
    }
    
    void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
    
      MODIFIERKEYS beforeMod;
      *((uint8_t*)&beforeMod) = before;
    
      MODIFIERKEYS afterMod;
      *((uint8_t*)&afterMod) = after;
    
      if (before != after) {
        if (modifyModifier(beforeMod, afterMod))
        {
          return;
        }
        Serial.print("Modifer changed:");
        Serial.println(after);
      }
      keyReport.modifiers = after;
    
      if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {
        Serial.println("LeftCtrl changed");
      }
      if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {
        Serial.println("LeftShift changed");
      }
      if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {
        Serial.println("LeftAlt changed");
      }
      if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {
        Serial.println("LeftGUI changed");
      }
    
      if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {
        Serial.println("RightCtrl changed");
      }
      if (beforeMod.bmRightShift != afterMod.bmRightShift) {
        Serial.println("RightShift changed");
      }
      if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {
        Serial.println("RightAlt changed");
      }
      if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {
        Serial.println("RightGUI changed");
      }
    
    }
    
    //void KbdRptParser::OnKeyPressed(uint8_t key)
    //{
    //  Serial.print("ASCII: ");
    //  Serial.println((char)key);
    //  Keyboard.write(key);
    //};
    
    USB     Usb;
    USBHub     Hub(&Usb);
    
    HIDBoot < USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE > HidComposite(&Usb);
    HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);
    HIDBoot<USB_HID_PROTOCOL_MOUSE>    HidMouse(&Usb);
    
    KbdRptParser KbdPrs;
    MouseRptParser MousePrs;
    
    void setup()
    {
      Serial.begin( 9600 );
    #if 0 // シリアル接続待ちするので無効化 #if !defined(__MIPSEL__)
      while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
    #endif
      Serial.println("Start");
    
      if (Usb.Init() == -1)
        Serial.println("OSC did not start.");
    
      delay( 200 );
    
      HidComposite.SetReportParser(0, &KbdPrs);
      HidComposite.SetReportParser(1, &MousePrs);
      HidKeyboard.SetReportParser(0, &KbdPrs);
      HidMouse.SetReportParser(0, &MousePrs);
    
      Mouse.begin();
      Keyboard.begin();
    }
    
    void loop()
    {
      Usb.Task();
    }
    

    좋은 웹페이지 즐겨찾기