Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Embedded Swiftで作る自作USBデバイス によるiOSデバイスの自動テスト / i...

Avatar for glassfiber glassfiber
September 16, 2026

Embedded Swiftで作る自作USBデバイス によるiOSデバイスの自動テスト / iOSDC Japan 2026 glassfiber

Avatar for glassfiber

glassfiber

September 16, 2026

More Decks by glassfiber

Other Decks in Programming

Transcript

  1. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber iOS Engineer @ pixiv glass

    ber • iPad用お絵描きアプリ Pastela の開発に従事 • 元ゲーム開発者 • iOSDC 2024 ルーキーズLT fi 2
  2. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber 目的 実機をXCTestを経由せず操作してみたい ・iPadはキーボードやマウスなどの外部デバイスを接続して操作できる ・外部からマウスのような操作を入力できるデバイスがあれば自動で操作できそう Embedded

    Swiftで実用品を作りたい ・最近Embedded Swiftが話題で、iOSエンジニアとして挑戦してみたい ・単なる学習用ではなく、実際の開発課題につながるものがやりたい →iPadに接続し、任意の位置をタップ・ドラッグする専用入力デバイスを作りたい 5
  3. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber iPadに接続できる入力デバイス iPadはキーボードやマウスを接続して操作できる ・これらはHuman Interface Device(HID)と呼ばれる

    自分のプログラムで制御可能なHIDを作り、iPadを外部から操作 ・HIDを自作するのにマイコンボードを使うことが多い ・開発にEmbedded Swiftが使えるもの 6
  4. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber マイコンボードでUSB HIDデバイスを作る Embedded Swiftが対応しているメジャーなマイコンボード ・Raspberry

    Pi Picoシリーズ ・ESP32シリーズ 今回はRaspberry Pi Pico 2 Wを使用 ・USBとBluetoothを扱える Raspberry Pi Picoシリーズ ・安価かつ容易に入手できる ・ドキュメントや作例が豊富 ・すでに所有していた ESP32シリーズ 7
  5. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber 作成したものの全体構成 ・Raspberry Pi Pico 2

    W(Pico) をiPadに接続 iPad HIDとして振る舞い、iPadを操作する ・PCからPicoにBluetooth(BLE)で操作スクリプトを送信 Picoのファームウェア記述はCとEmbedded Swiftの混合 iPad USB HID 画面操作 ・HIDとBLEの制御部分はCで記述 Cで書かれた既存のライブラリが充実しているためそのまま利用 ・Pico SDK - Pico向けの公式C/C++開発環境 ・TinyUSB - PicoをUSB機器として動かすライブラリ ・BTstack - PicoでBluetooth通信を行うライブラリ ・操作データの管理部分をEmbedded Swiftで記述 Swiftの配列やenumなどを使って書ける 8 BLE スクリプト送信
  6. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Report Descriptor └─ Usage Page

    (Generic Desktop) └─ Usage (Mouse) └─ Collection (Application) ├─ Usage Page(Button) └─ Usage Page(Generic Desktop) ├─ Usage (X) ├─ Usage (Y) └─ Input (Data, Variable, Relative) HID動作の概要 USB規格書にあるHIDの仕様を参照 https://www.usb.org/hid まず、デバイス側がReport Descriptorで データ構造を定義する マウスのReport Descriptorの例(抜粋) デバイスは定義した構造に従ってInput Reportを送信する ホスト側はReport Descriptorに基づいてInput Reportを解釈する マウスやキーボードなどよく使われるデバイスは Report Descriptor の構成がある程度定型化している Report Descriptorをどう解釈するかはホスト側次第 ・解釈できない場合は動作しない 9
  7. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber マウスのReport Descriptorの例 ・デバイスの種類はマウス Usage Page

    (Generic Desktop) Usage (Mouse) ・ボタンは3つ Usage Mimum (1), Usage Maximum (3) : 番号1〜3 Report Count (3) : 個数3 ・XとYは-127〜127の範囲で 相対的(Relative)な値 Logical Minumum (-127), Logical Maximum (127) Input (Data, Variable, Relative) 10 Usage Page (Generic Desktop), Usage (Mouse), Collection (Application), Usage (Pointer), Collection (Physical), Usage Page (Buttons), Usage Minimum (1), Usage Maximum (3), Logical Minimum (0), Logical Maximum (1), Report Count (3), Report Size (1), Input (Data, Variable, Absolute), // 3 button bits Report Count (1), Report Size (5), Input (Constant), // 5 bit padding Usage Page (Generic Desktop), Usage (X), Usage (Y), Logical Minimum (-127), Logical Maximum (127), Report Size (8), Report Count (2), Input (Data, Variable, Relative), // X and Y End Collection, End Collection
  8. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber さまざまなHID HIDの規格ではマウスやキーボード以外にも さまざまな機器が定義されている Touch Screen,

    Pen, Digitizer など、絶対座標を指定できるものがい くつかある →これらを使ったらiPadで画面の任意の位置を操作できるのでは… しかし検証してみたところ、iPad OSでは認識しなかった 11
  9. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Report Descriptorを調べる マウスとTouch ScreenのReport Descriptorを比較してみる

    ・デバイスの種類が異なる Generic Desktop/Mouse と Digitizers/Touch Screen ・座標の属性が異なる Relative と Absolute デバイスの種類をマウスに したまま、座標の属性を Absoluteにしたら絶対座標で 指定できないだろうか? Touch Screen Usage Page (Generic Desktop), Logical Maximum (4095), マウス Usage Page (Generic Desktop), Report Size (16), ... Usage (X), Usage (X), Usage (Y), ... Logical Minimum (-127), Input (Data, Variable, Absolute), Logical Maximum (127), Usage (Y), Report Size (8), ... Report Count (2), Input (Data, Variable, Relative), Input (Data, Variable, Absolute), 12
  10. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Absoluteで座標指定するマウス Descriptorで座標値の範囲を指定 今回は画面の範囲で指定できればよいため、 16bitの整数値で0…32767とする →絶対座標で指定できた!

    マウスカーソルが指定した位置に ジャンプする動き 13 Absolute Mouse Usage Page (Generic Desktop), Usage (X), Usage (Y), Logical Minimum (0), Logical Maximum (32767), Report Size (16), Report Count (2), Input (Data, Variable, Absolute),
  11. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber マウスボタンの入力(TapやDrag) 指定座標への移動に成功したのでボタン入力に対応する Descriptionのボタンに関する部分は通常のマウスと同じ Button DownとButton

    Upを送るだけ …のはずがボタンのUpが伝わらない現象が発生 座標移動後、Button Downは反応するがButton Upはアプリへ伝わらず、 押されっぱなしの状態になる 20
  12. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Embedded Swiftのコードを書く ここまでは移動やクリックの処理 などをすべてCで書いていた→ HID動作の目処がたったので、当初

    の目的であるEmbedded Swiftを 書きたい 25 #define DEMO_POINT(_delay, _buttons, _x, _y) \ {_delay, PICOTAB_EVENT_POINTER_REPORT, _buttons, _x, _y, 0, 0} static const picotab_script_event_t bootsel_demo_events[] = { DEMO_POINT(1500, 0, UI_NEW_CANVAS_BUTTON_X, UI_NEW_CANVAS_BUTTON_Y), DEMO_POINT(UI_CLICK_HOLD_MS, DEMO_PRIMARY_BUTTON, UI_NEW_CANVAS_BUTTON_X, UI_NEW_CANVAS_BUTTON_Y), DEMO_POINT(UI_OPEN_PRESET_WAIT_MS, 0, UI_NEW_CANVAS_BUTTON_X, UI_NEW_CANVAS_BUTTON_Y), DEMO_POINT(500, 0, UI_SQUARE_PRESET_X, UI_SQUARE_PRESET_Y), DEMO_POINT(UI_CLICK_HOLD_MS, DEMO_PRIMARY_BUTTON, UI_SQUARE_PRESET_X, UI_SQUARE_PRESET_Y), DEMO_POINT(UI_CREATE_CANVAS_WAIT_MS, 0, UI_SQUARE_PRESET_X, UI_SQUARE_PRESET_Y), : : DEMO_POINT(DRAW_INTERVAL_MS, DEMO_PRIMARY_BUTTON, DRAW_STAR_1_X, DRAW_STAR_1_Y), DEMO_POINT(0, 0, DRAW_STAR_1_X, DRAW_STAR_1_Y), }; #undef DEMO_POINT
  13. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Embedded Swiftのビルド環境をつくる Visual Studio Code

    + Pico SDK ・Embedded Swiftコンパイラをインストール "Installing Embedded Swift"*1に従い、swiftlyを使ってSwiftコンパ イラのDevelopment Snapshotをインストール ・Embedded SwiftコードのコンパイルができるCMake設定など →AIで解決 (CMakeわからない…) *1 https://docs.swift.org/latest/documentation/embeddedswift/installembeddedswift 26
  14. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Embedded Swift で書き直す enum ScriptEventKind:

    UInt8 { case mouse case keyboard case wait } 操作データとその配列 →Swiftのenumとstructで表現 [ScriptEvent]として保持 再生時にイベントを1件ずつHIDレ ポートへ変換 struct MouseEvent { let buttons: UInt8 let x: Int16 let y: Int16 } struct ScriptEvent { let delayAfterMs: UInt16 let kind: ScriptEventKind let mouse: MouseEvent let keyboard: KeyboardEvent (比較的) } Swiftらしく書けるようになった let events: [ScriptEvent] 27
  15. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber [86/86] Linking CXX executable picotab.elf

    開発中に詰まった問題 DemoScript.swift.o: undefined reference to `posix_memalign' events: [ScriptEvent] 配列のデータを増やして いったらリンクエラーが出るようになった DemoScript.swift.o: undefined reference to `posix_memalign' collect2: error: ld returned 1 exit status ninja: build stopped: subcommand failed. 原因はposix_memalign関数がないこと ・要素数が大きくなると動的メモリ確保が生成される → Embedded Swiftが posix_memalign を要求するが Pico SDK側に実装がなく、リンクエラー Embedded Swiftは大きなArrayの領域確保に posix_memalign を使用するが 今回 Pico SDKで使用している Newlib には posix_memalign がなかった ※Embedded Swiftドキュメントの必要な外部依存に posix_memalignとfree が書かれている https://docs.swift.org/latest/documentation/embeddedswift/externaldependencies/ 28
  16. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Newlibとは 組み込み向けのlibc実装 ・ISO Cの機能を提供する ・OSを前提とするPOSIX

    APIの posix_memalign は含まれない 対応 aligned_alloc を使い posix_memalign 互換実装を作成 (aligned_alloc はISO C11で規定された標準Cライブラリ関数) →無事ビルド可能に 29
  17. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber Embedded Swiftで動作するようになった 現状の手順 1. Swiftコード上に操作スクリプトの配列を直接記述

    2. ビルドしてPCに接続したPicoに転送 3. PicoをiPadに接続しなおして再生ボタンを押す 4. なんかおかしければ1.に戻る あまりにもめんどくさい… →操作スクリプトをビルド時でなく外から送り込みたい 30
  18. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber 操作スクリプトをBLEで転送 PicoはiPadにUSBで接続されていて、Bluetoothは未使用 iPad →Bluetooth(BLE)でPCと接続し、データを受信できる ※当初、画面操作をBluetooth

    HIDで行うことも検討したが、 USB HID 画面操作 Absolute指定がうまく動作しなかったため断念 1. PCで操作内容を編集 2. スクリプト全体をBLEでPicoに転送 3. Picoがスクリプトを再生、HIDでiPadを操作 31 BLE スクリプト送信
  19. Embedd ed Swif tで作る自作USBデバイスによるiO Sデバイスの自動テスト|glassfiber まとめ ・Raspberry Pi Pico 2

    WでUSBデバイスを作ってiPadを操作することができた ・座標値をAbsoluteとすることで絶対座標で操作の指定が可能 ・ボタンがうまく動作しない現象はもう1つマウスを追加することで回避できる ・Embedded SwiftとCを混在してプログラムの記述ができた ・Cで書いていたものをEmbedded Swiftに置き換えて書きやすく ・Embedded Swiftで必要な外部依存関数について理解 ・BLEでPCから操作スクリプトを送信し、PCからiPadを操作できるようになった ・実機自動テストへ発展させられる可能性 ・テスト環境をハードウェアごと作るのは楽しい 35