ユーザ用ツール

サイト用ツール


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

差分

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

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
ハイハイスクールアドベンチャー_raspberry_pico_lcd版 [2025/04/14 01:17] – [Pico-ResTouch-LCD-2.8] arakiハイハイスクールアドベンチャー_raspberry_pico_lcd版 [2025/04/17 01:04] (現在) – [BLEキーボード] araki
行 126: 行 126:
 === 間違ったWEAK宣言の呪縛 === === 間違ったWEAK宣言の呪縛 ===
  
-コンパイラというかリンカーへの指示として、WEAKシンボルというのが太の昔から存在しています。+コンパイラというかリンカーへの指示として、WEAKシンボルというのが太の昔から存在しています。
 何かというと、そのシンボルはリンク時に他にWEAKではない同名のシンボルがあればそれで置き換えるというものです。 何かというと、そのシンボルはリンク時に他にWEAKではない同名のシンボルがあればそれで置き換えるというものです。
 普通同じシンボルが別々に実体をもっていたらリンク時に重複エラーになるんですが、WEAKがついていれば、それが起きません。 普通同じシンボルが別々に実体をもっていたらリンク時に重複エラーになるんですが、WEAKがついていれば、それが起きません。
行 233: 行 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キーボード ====
行 286: 行 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>
  
 +ついに、文字が拾えるようになりました。
 +まだ、テスト用のコードなので、これを整理して、こちらに組み込まないといけないのですが、長かった。
  
 +ポイントは、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版.1744593469.txt.gz · 最終更新: 2025/04/14 01:17 by araki