ユーザ用ツール

サイト用ツール


ハイハイスクールアドベンチャー_raspberry_pico_lcd版

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
ハイハイスクールアドベンチャー_raspberry_pico_lcd版 [2025/04/14 01:02] arakiハイハイスクールアドベンチャー_raspberry_pico_lcd版 [2025/04/17 23:26] (現在) – [USBキーボード] araki
行 19: 行 19:
 STT7789 という、よくあるコントローラで 240x320の液晶(タッチパネル/TFカードスロット込み)です。 STT7789 という、よくあるコントローラで 240x320の液晶(タッチパネル/TFカードスロット込み)です。
 [[https://github.com/lovyan03/LovyanGFX|LovyanGFX]] であっさり動くだろうと思っていたら、全然表示が来なくて大変苦労しました。 [[https://github.com/lovyan03/LovyanGFX|LovyanGFX]] であっさり動くだろうと思っていたら、全然表示が来なくて大変苦労しました。
 +
 +ちなみにピン配置は以下の通り。
 +
 +^名前^番号^
 +|LCD_SLCK/SD_SCK|10|
 +|LCD_MOSI/SD_TX|11|
 +|LCD_MISO/SD_RX|12|
 +|LCD_BL|13|
 +|LCD_DC|14|
 +|LCD_RST|15|
 +|SD_CS|22|
 +
 +ちなみに、液晶パネルとSDカードはSPI1を共有しています((なので一部ピンが共用されている。))
  
 原因はバックライトのコントロールにありました。 原因はバックライトのコントロールにありました。
行 27: 行 40:
 まあ、描画はされていたけれど、バックライトが真っ暗で何も見えていなかっただけというのが実際だったわけです。 まあ、描画はされていたけれど、バックライトが真っ暗で何も見えていなかっただけというのが実際だったわけです。
  
-<code>+<code cpp>
 namespace lgfx namespace lgfx
 { {
行 60: 行 73:
 </code> </code>
  
-<code>+<code cpp>
 namespace lgfx namespace lgfx
 { {
行 94: 行 107:
 </code> </code>
  
 +SPI1を共用しているので、LCD/SDの初期化には注意が必要です。
 +LCDを先に初期化している前提で話しますが、この場合SDカードインターフェイスの初期化時に SPI1.setCS(22)のように、CSピンをセットしに行くと固まってしまいます。
  
 +SDカードのCSピンは SD.begin(22,SPI1)のように、SDインターフェイスの開始時に渡せばいいので、setCS()は呼ばないようにしてください。
  
 ==== USBキーボード ==== ==== USBキーボード ====
行 110: 行 126:
 === 間違ったWEAK宣言の呪縛 === === 間違ったWEAK宣言の呪縛 ===
  
-コンパイラというかリンカーへの指示として、WEAKシンボルというのが太の昔から存在しています。+コンパイラというかリンカーへの指示として、WEAKシンボルというのが太の昔から存在しています。
 何かというと、そのシンボルはリンク時に他にWEAKではない同名のシンボルがあればそれで置き換えるというものです。 何かというと、そのシンボルはリンク時に他にWEAKではない同名のシンボルがあればそれで置き換えるというものです。
 普通同じシンボルが別々に実体をもっていたらリンク時に重複エラーになるんですが、WEAKがついていれば、それが起きません。 普通同じシンボルが別々に実体をもっていたらリンク時に重複エラーになるんですが、WEAKがついていれば、それが起きません。
行 137: 行 153:
 ちょっとWeb界隈を漁ると、同じ現象で困っている人もいらっしゃる。 ちょっとWeb界隈を漁ると、同じ現象で困っている人もいらっしゃる。
  
-で、さらに調べていったら、**ヘッダファイルの中でコールバックのテンプレート宣言に__attribute((weak))__つけてる**じゃありませんか!+で、さらに調べていったら、**ヘッダファイルの中でコールバックのテンプレート宣言に**<code cpp>__attribute__((weak))</code>**つけてる**じゃありませんか!
 ダメ、絶対! ダメ、絶対!
 WEAK属性は実装の方にだけつけて宣言につけちゃダメ! WEAK属性は実装の方にだけつけて宣言につけちゃダメ!
行 152: 行 168:
  
 それが usbkbd.cppなのです。 それが usbkbd.cppなのです。
-<code>+<code cpp>
 // Tiny USB HID callback entry points to avoid wrong weak attribute usabe in Adafruit TinyUSB // Tiny USB HID callback entry points to avoid wrong weak attribute usabe in Adafruit TinyUSB
  
行 206: 行 222:
 tuh_hid_report_received_cb()の最後に次のコールバックを要求する処理が入っているのです。 tuh_hid_report_received_cb()の最後に次のコールバックを要求する処理が入っているのです。
  
-<code>+<code cpp>
 if (!tuh_hid_received_report(dev_addr, instance)) if (!tuh_hid_received_report(dev_addr, instance))
 { {
行 217: 行 233:
 されどこれだけ。 されどこれだけ。
  
 +=== キーマッピング ===
 +
 +US配列のキーボードがターゲットなのは、Keyboard.cpp内の keycode2asciiという配列がそうなっているからです。
 +HID_KEYCODE_TO_ASCIIというTinyUSB由来のマッピングを横着して使っているのでこうなっています。
 +
 +これを、JISキーボードにあうように直せばJISキーボードでも使えます。
 +
 +<code cpp>
 +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
 +</code>
  
 ==== BLEキーボード ==== ==== BLEキーボード ====
行 270: 行 296:
 わたしの手元にあるバッファローのBLEキーボードとM5 CardputerのおまけでついてくるBLEキーボードだけがセキュア接続でなくてもつながるキーボードなので、つまりは、大体の場合セキュアじゃないとダメなのです。((ちなみにCardputerのそれはセキュアでは接続できません。バッファローはセキュアでもOK)) わたしの手元にあるバッファローのBLEキーボードとM5 CardputerのおまけでついてくるBLEキーボードだけがセキュア接続でなくてもつながるキーボードなので、つまりは、大体の場合セキュアじゃないとダメなのです。((ちなみにCardputerのそれはセキュアでは接続できません。バッファローはセキュアでもOK))
  
-さて世間に、実は Pico W + btstack でセキュア接続をして BLE Centralとして動作させてるという事例があまりないよう、AIもいろいろ教えてくれるんでが、簡単にいうと、セキュア接続要求がstate=8で失敗して先へ進めないが現状です。+とりあえずボンディング行わない単純にコネクションだけをセキュアにできればいいので、そのように設定を。 
 +<code cpp> 
 +  sm_init();                        // セキュリティマネージャの初期化 
 +  sm_set_request_security(true);    // セキュリティ要求を有効化 
 +  sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT); // IOキャパビリティ設定 
 +  sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION); // 認証要件を設定 
 +  sm_set_encryption_key_size_range(7, 16); // 暗号化キーサイズ範囲を設定
  
-まあ、キュアじゃなくもつながキーボードなら多分つながるのでそれでよしとるというのもありしょうけれど、んかあとちょっと工夫動くんじゃないかっていう気がする、あきらめがつきません+  sm_event_callback_registration.callback = &sm_event_handler; 
 +  sm_add_event_handler(&sm_event_callback_registration); 
 +</code> 
 + 
 +IO_CAPABILITY_NO_INPUT_NO_OUTPUTとSM_AUtHREQ_SECURE_CONNECTIONのみがットされ場合、Just in Workでの接続行われようです。なで、sm_event_handler側でそれを処理ればいようです。 
 + 
 +<code cpp> 
 +static void 
 +sm_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { 
 +  if (packet_type != HCI_EVENT_PACKET) return; 
 + 
 +  switch (hci_event_packet_get_type(packet))  
 +  { 
 +    case SM_EVENT_JUST_WORKS_REQUEST: 
 +      { 
 +        // Just Works Confirmを自動的に承認 
 +        bd_addr_t addr; 
 +        sm_event_just_works_request_get_address(packet, addr); // アドレスを取得 
 +        Serial.printf("Just works request from %s\n", bd_addr_to_str(addr)); 
 +        sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); 
 +        break; 
 +      } 
 +    case SM_EVENT_PAIRING_STARTED: 
 +      Serial.println("Pairing started."); 
 +      break; 
 +    case SM_EVENT_PAIRING_COMPLETE:  
 +    { 
 +      uint8_t status = sm_event_pairing_complete_get_status(packet); 
 +      if (status == ERROR_CODE_SUCCESS)  
 +      { 
 +        Serial.println("Pairing complete. Connection is now secure."); 
 +        hci_con_handle_t connection_handle = sm_event_pairing_complete_get_handle(packet); 
 +        uint16_t hids_cid; 
 +イスに接続 
 +        gatt_client_discover_primary_services_by_uuid16(&handle_gatt_client_event, connection_handle, HID_SERVICE_UUID);  // GATT event handler 
 +      }  
 +      else  
 +      { 
 +        Serial.printf("Pairing failed with status %u.\n", status); 
 +      } 
 +      break; 
 +    } 
 +    case SM_EVENT_PASSKEY_DISPLAY_NUMBER: 
 +      // パスキー表示が必要な場合の処理 (今回は No Input No Output なので基本的には発生しない
 +      display.printf("Passkey: %06u\n", sm_event_passkey_display_number_get_passkey(packet)); 
 +      break; 
 +    case SM_EVENT_REENCRYPTION_STARTED: 
 +      { 
 +        // 再暗号化開始された場合の処理 
 +        bd_addr_t addr; 
 +        sm_event_reencryption_started_get_address(packet, addr); // アドレスを取得 
 +        uint8_t addr_type = sm_event_reencryption_started_get_addr_type(packet); 
 +        Serial.printf("Re-encryption started for address: %s (%d)\n", bd_addr_to_str(addr), addr_type); 
 +        break; 
 +      } 
 +    case SM_EVENT_REENCRYPTION_COMPLETE: 
 +      { 
 +        // 再暗号化が完了した場合の処理 
 +        uint8_t status = sm_event_reencryption_complete_get_status(packet); 
 +        if(status == ERROR_CODE_SUCCESS) { 
 +          Serial.println("Re-encryption successful."); 
 +        } else { 
 +          Serial.printf("Re-encryption failed.(%d)\n", status); 
 +        } 
 +        break; 
 +      } 
 +    default: 
 +      break; 
 +  } 
 +
 +</code> 
 + 
 +あとは接続時にセキュア接続を要求するだけ 
 + 
 +<code cpp> 
 +    case HCI_EVENT_LE_META: 
 +      if (hci_event_le_meta_get_subevent_code(packet) == HCI_SUBEVENT_LE_CONNECTION_COMPLETE)  
 +      { 
 +        // 暗号化を有効化 
 +        hci_con_handle_t connection_handle = gap_subevent_le_connection_complete_get_connection_handle(packet); 
 +        gap_request_security_level(connection_handle, LEVEL_2); 
 +        sm_request_pairing(connection_handle); 
 +        //gatt_client_discover_primary_services_by_uuid16(&handle_gatt_client_event, connection_handle, HID_SERVICE_UUID);  // GATT event handler 
 +        Serial.printf("Connected to HID device: %s (%08x)\n", bd_addr_to_str(keyboard_address), connection_handle); 
 +      } 
 +      break; 
 +</code>
  
-識者の見解を待ちす!+これでコネクションはセキュアになりした。
  
 +<del>ただ、まだキーボードから通知が拾えていません。
 +ble/hids_client.c というのがあるので、これを使えば簡単かもしれませんが、サンプルが見当たらないので、ソースを読みながら手探りで調査しています。</del>
  
 +ついに、文字が拾えるようになりました。
 +<del>まだ、テスト用のコードなので、これを整理して、こちらに組み込まないといけないのですが、長かった。</del>
  
 +ポイントは、Notificationを受け取りたいCharacteristicに対して、ディスクリプタを検索してCCCDを見つけたら、Notifyを送信するように要求する((0x0001 -- little endian なら {0x01, 0x00}を送信する。))のと、最後に gatt_client_listen_for_charcteristic_value_updates()でGATT_EVENT_NOTIFICATIONを受け取るようにすることの両方。
  
 +更に gatt_client_listen_for_characteristic_value_updates()のcharacteristicにはnullptrを渡して一括でやる方がいいということですかね。((サンプルに従って notification_listenerを一つだけ作っているので、個別の characteristicに対してやりたいなら、多分これもcharacteristicごとにわけないといけないんだと思いますが、一括で動いているのでよしとします。))
  
  
ハイハイスクールアドベンチャー_raspberry_pico_lcd版.1744592563.txt.gz · 最終更新: 2025/04/14 01:02 by araki