Skip to content

Instantly share code, notes, and snippets.

@bellx2
Created May 25, 2026 22:10
Show Gist options
  • Select an option

  • Save bellx2/743589236253d9a04319af41bfd5369c to your computer and use it in GitHub Desktop.

Select an option

Save bellx2/743589236253d9a04319af41bfd5369c to your computer and use it in GitHub Desktop.
Upload

プロトコル仕様 (推定)

dev_data/trans.pcap を解析して判明した、3coins ワイヤレストランシーバーの通信仕様。 本書は観測ベースの推定であり、メーカー公式の仕様書ではない。

レイヤ構成

802.11 (radiotap) → LLC/SNAP → IPv4 → UDP → 独自プロトコル

子機2台 (192.168.1.1192.168.1.100) が802.11上で直接または同一APを介してIP通信し、UDPで映像・音声・制御を送り合う。両機が同時に送受信する全二重動作。

UDPポート割り当て

ポート (送信元) 用途 典型ペイロード長 パケットレート
11011 / 11013 映像 (MJPEG) 1336B (中間), 末尾は可変 約44 pps
5008 音声 270B 固定 約50 pps
11012 / 11014 制御/keep-alive 28B 固定 数 pps

それぞれ送信側と受信側のポートはペアになっている (11011↔11013 など)。

1. 映像プロトコル (UDP 11011/11013)

フレームの組み立て

1枚のJPEG画像 (FFD8 ... FFD9) を1〜数十個のUDPパケットに分割して送る。各パケットは20バイトのカスタムヘッダ + JPEGフラグメントを持つ。

20バイトヘッダ

Offset Size フィールド 説明
0 1 flag_and_frame_lo 上位nibble = フラグ、下位nibble = フレーム番号 mod 16
1 1 frag_seq フレーム内フラグメント連番 (0始まり)
2 2 proto_ver バージョン/フラグ。観測値 0x0604, 0x0704
4 4 frame_id (LE u32) フレームID。フレーム毎に増分
8 4 stream_const 固定 0x03000000
12 4 padding 固定 0x00000000
16 4 frag_bitmask (BE u32) このパケットまでの累積ビットマスク = 2^(frag_seq+1) - 1

byte 0 のフラグ (上位nibble)

意味
0x8 フレーム先頭パケット (このパケットの直後に FFD8 が現れる)
0x0 中間パケット
0x4 フレーム末尾パケット (末尾近くに FFD9 が現れる)

下位nibble (frame_lo) は frame_id の下位4bitを使ってもよいが、観測値は単純なフレーム連番 (1, 2, 3, ... mod 16) として動く。

byte 16-19 の frag_bitmask

2^(frag_seq+1) - 1 を big-endian で詰めたもの。例:

frag_seq frag_bitmask
0 00 00 00 01
1 00 00 00 03
2 00 00 00 07
3 00 00 00 0f
4 00 00 00 1f
5 00 00 00 3f

これは「ここまでに何個のフラグメントを送ったか」を毎パケット示すための累積マスク。受信側が欠落フラグメントを検知できる。

フレーム再構築の手順

  1. UDPペイロードの先頭20Bを剥がす。
  2. frame_id でグループ化。
  3. 各フレーム内で frag_seq 順にソートして連結。
  4. 先頭が FFD8 で始まり末尾が FFD9 で終わる完全なJPEGバイト列になる。
  5. frag_bitmask の最大値や flag=0x4 の有無で「最終フラグメント受信済み」と判定する。

無線環境のため重複パケット (frame_id + frag_seq が同一) が観測される。先勝ち or 後勝ちのどちらでもよい。

JPEG仕様

  • baseline DCT
  • 320 × 240, YCbCr 4:2:0, 8-bit precision
  • 標準的なJPEG構造 (DQT / SOF0 / DHT / SOS / 圧縮データ / EOI)
  • 観測実効フレームレート 約8〜9 fps

2. 音声プロトコル (UDP 5008)

パケット仕様

UDPペイロード270バイト固定 (UDP長278B = 8B UDPヘッダ + 270Bペイロード)。

Offset Size フィールド 説明
0 2 seq_a (LE u16) パケット連番
2 2 seq_b (LE u16) 別系統連番 (おそらくストリーム内seq)
4 4 timestamp (LE u32) タイムスタンプ/グローバル連番
8 4 session_id 送信元固有のセッションID (例: 01 41 b4 f7, 4d ac fe 2a)
12 2 counter (LE u16) per-packetカウンタ
14 2 marker 固定 0x5480
16 2 marker 固定 0x5480
18 2 reserved 通常 0x0000
20 250 samples オーディオサンプル本体

音声フォーマット (推定)

  • サンプリング周波数: 8000 Hz (一般的なテレフォニー帯域)
  • ビット深度: 16-bit signed PCM
  • チャンネル: モノラル
  • エンディアン: little-endian
  • 1パケット = 250 byte = 125 サンプル = 15.625ms 分

データレート: 250B × 50pps ≈ 12.5 kB/s。8kHz × 2byte = 16 kB/s より少し低いのは、無音区間で送信を間引いている、もしくは推定サンプルレートが若干違う可能性あり。

無音検出

観測したキャプチャでは、両方向ともサンプル部の非ゼロ率が 0.03〜0.07% と極めて低く、実質的に完全な無音だった。PTT (Push-To-Talk) ボタン未押下時にもストリーム自体は流し続け、ペイロードは 0x00 で埋める仕様と思われる。

3. 制御チャネル / シグナリング (UDP 11012/11014)

20バイト固定ペイロード (UDP長28B)。ハートビート + 呼び出しシグナリング + セッション中通知がこの1ポートに同居している。各メッセージは payload の byte0 (ステートコード) で識別する。

3.1 アイドル時のハートビート

03 ff 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00

両方向から約1Hzで送信。byte0=0x03, byte1=0xff が "idle" を示す。

3.2 通話開始ハンドシェイク

観測キャプチャでの呼び出し → 映像開始までのシーケンス:

時刻 (相対) 方向 byte0-1 ペイロード末尾 意味(推定)
12.013 1.1→1.100 03 ff × 4 idle 呼び出し前の連打
12.021 1.100→1.1 09 4b 0埋め (a) 呼び出し応答(REQ)
12.024 1.1→1.100 59 4b 0埋め (b) 確認(ACK, a XOR 0x50)
15.027 1.1→1.100 03 ff 末尾6Bに fa a9 4c b8 7e 17 (c) セッションID提示
15.948 1.1→1.100 0c 00 0埋め (d) START要求(REQ)
15.951 1.100→1.1 5c 00 0埋め (e) OK応答(ACK, d XOR 0x50)
16.026 1.1→1.100 (映像 UDP 11011/11013) 映像ストリーム開始(e の75ms後)

3.3 ACK の符号化規則

リクエスト/レスポンスのペアは byte0 を XOR 0x50 することで応答を表す:

0x09 (REQ) -> 0x59 (ACK)
0x0c (REQ) -> 0x5c (ACK)

0x50 = bit4 + bit6。「リクエストの byte0 に 0x50 を OR」だけの単純なエンコーディング。SIPのような多段階レスポンスは持たず、各種state変化はすべて1往復で完結する。

3.4 セッション中通知

通話確立後にも 1.100→1.1 方向で散発的に 44 バイト長のメッセージが流れる:

t=19.645  02 53 00 00 20 00 00 00 ... 07 00 00 00 ...
t=20.137  02 55 00 00 24 00 00 00 ... 07 00 00 00 ...
t=32.605  02 6f 00 00 11 00 00 00 ... 04 00 00 00 ...

書式: 02 [seq8] 00 00 [counter32 LE] ... [code8] 00 00 00 ...。1.100 側からのみ観測。状態通知ないし品質報告と推測されるが未解析。

4. その他の小ノイズ

tshark で IP src を見ると 802.11 受信エラーで radiotap デコードがズレ、192.168.81.6289.119.100.2 のような無関係IPで5008/11011を名乗るパケットが極稀に観測される。フレーム数1で内容も正常パケットの劣化コピーなので無視してよい。

まとめ

このプロトコルは独自仕様ながら構造は素直で、

  • 映像 = カスタム断片化ヘッダ + 標準JPEG
  • 音声 = カスタムシーケンスヘッダ + 生PCMサンプル

の組み合わせ。RTP風だがRTP互換ではない。バージョン情報やセッションID、累積ビットマスクなど、無線環境でのロス検知を意識した最小限の構造になっている。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment