# 通知設計書 44-VTベル鳴動通知

## 概要

本ドキュメントは、FreeBSD カーネルの VT（仮想ターミナル）サブシステムが、ターミナルベル（BEL文字）を受信した際に発行する devctl 通知「VT / BELL / RING」の設計を記述する。

### 本通知の処理概要

VT コンソールドライバにおいて、アプリケーションがターミナルベル文字（0x07）を出力した際に、ベルの状態情報（有効/無効、消音状態、周波数、持続時間）をユーザーランドに通知する。

**業務上の目的・背景**：従来のターミナルベルはスピーカーのビープ音として実装されていたが、現代のシステムでは視覚的通知や他の通知手段への変換が求められる。この devctl 通知により、devd(8) 経由で視覚的フラッシュ、サウンドファイルの再生、デスクトップ通知など、多様な通知手段を実現できる。アクセシビリティ対応においても重要な機能である。

**通知の送信タイミング**：VT ターミナルが BEL 文字（\a, 0x07）を受信するか、ioctl による音響パラメータ付きベル要求を処理した際に送信される。

**通知の受信者**：devd(8) デーモンを経由して、デスクトップ環境のアクセシビリティツールやサウンドデーモンが受信する。

**通知内容の概要**：ベルの有効/無効状態、消音（hushed）状態、周波数（Hz）、持続時間（ミリ秒）が含まれる。

**期待されるアクション**：受信者はベルイベントに応じて、視覚的フラッシュ表示、サウンド再生、ログ記録などのアクションを実行する。enabled=false の場合は通知のみでベル音は鳴らない。

## 通知種別

devctl カーネル通知（devd(8) 経由のシステムイベント通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（カーネル内 devctl_notify） |
| 優先度 | 低 |
| リトライ | 無 |

### 送信先決定ロジック

devctl_notify() によりカーネルの devctl キューに投入される。

## 通知テンプレート

### devctl 通知フォーマット

| 項目 | 内容 |
|-----|------|
| system | VT |
| subsystem | BELL |
| type | RING |
| data | enabled=... hushed=... hz=... duration_ms=... |

### 本文テンプレート

```
!system=VT subsystem=BELL type=RING
enabled=true hushed=false hz=800 duration_ms=125
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| enabled | ベル機能の有効/無効 | vt_enable_bell | Yes |
| hushed | 消音状態 | vd->vd_flags & VDF_QUIET_BELL | Yes |
| hz | ベル音の周波数（Hz） | vw->vw_bell_pitch / param計算値 | Yes |
| duration_ms | ベル音の持続時間（ミリ秒） | vw->vw_bell_duration / SBT_1MS | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ターミナル出力 | BEL 文字（0x07）受信 | vtterm_bell コールバック | 標準ベル文字による発行 |
| ioctl | KDMKTONE / KIOCSOUND ioctl | 音響パラメータ付きベル要求 | ioctl による周波数・持続時間指定ベル |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| メモリ割り当て失敗 | malloc(DEVCTL_LEN, M_VT, M_NOWAIT) が NULL の場合 |
| sbuf エラー | sbuf_error(&sb) != 0 の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[BEL文字受信 or ioctl] --> B[vtterm_devctl 呼び出し]
    B --> C{メモリ割り当て成功?}
    C -->|No| D[通知スキップ]
    C -->|Yes| E[sbuf に enabled/hushed/hz/duration を構築]
    E --> F{sbuf_error == 0?}
    F -->|Yes| G[devctl_notify VT/BELL/RING 発行]
    F -->|No| H[通知スキップ]
    G --> I[sbuf/buf 解放]
    H --> I
    D --> J[終了]
    I --> J
```

## データベース参照・更新仕様

### 参照テーブル一覧

| 構造体フィールド | 用途 | 備考 |
|-----------|------|------|
| vt_enable_bell | ベル有効フラグ | グローバル変数 |
| vd->vd_flags & VDF_QUIET_BELL | 消音フラグ | VT デバイス構造体 |
| vw->vw_bell_pitch | ベル周波数 | VT ウィンドウ構造体 |
| vw->vw_bell_duration | ベル持続時間 | sbintime_t 型 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メモリ不足 | malloc が M_NOWAIT で NULL を返した場合 | 通知をスキップ |
| バッファ溢れ | sbuf が 64 バイトを超えた場合 | sbuf_error が非ゼロとなり通知をスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 明示的な制限なし（ベル文字の出力頻度に依存） |
| 1日あたり上限 | 明示的な制限なし |

### 配信時間帯

制限なし

## セキュリティ考慮事項

- 通知にはデバイス固有の状態情報のみが含まれ、機密情報は含まれない
- /dev/devctl の読み取りには root 権限が必要
- ベル通知の頻度が高い場合、devctl キューの圧迫につながる可能性がある

## 備考

- DEVCTL_LEN は vtterm_devctl 内で 64 バイトに定義されている
- vt_enable_bell が false の場合でも devctl 通知自体は発行される（enabled=false として）
- hushed=true の場合はスピーカー音は鳴らないが、devctl 通知は発行される

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

VT デバイスとウィンドウの構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | vt.h | `sys/dev/vt/vt.h` | struct vt_device（vd_flags の VDF_QUIET_BELL）、struct vt_window（vw_bell_pitch, vw_bell_duration） |

**読解のコツ**: vt_enable_bell はグローバルな sysctl 変数、VDF_QUIET_BELL はデバイスごとのフラグである。両者の違いを理解すること。

#### Step 2: エントリーポイントを理解する

ベル通知の発行元である vtterm_devctl 関数を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | vt_core.c | `sys/dev/vt/vt_core.c` | vtterm_devctl()（行1101-1119）が通知の生成・発行を行う |

**主要処理フロー**:
1. **行1100**: DEVCTL_LEN = 64 の定義
2. **行1107-1108**: M_NOWAIT でバッファ割り当て
3. **行1110-1113**: sbuf に enabled, hushed, hz, duration_ms を構築
4. **行1115-1116**: sbuf エラーチェック後に devctl_notify("VT", "BELL", "RING", ...) 発行

#### Step 3: 呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | vt_core.c | `sys/dev/vt/vt_core.c` | vtterm_bell コールバック（行1127付近）と ioctl ハンドラ（行1167付近）から vtterm_devctl が呼ばれる |

**主要処理フロー**:
- **行1127**: vtterm_bell で vt_enable_bell, VDF_QUIET_BELL, vw_bell_pitch, vw_bell_duration を渡す
- **行1167**: ioctl ハンドラで周波数と持続時間のパラメータを計算して渡す

### プログラム呼び出し階層図

```
vtterm_bell()                              [ターミナル BEL 文字受信]
    |
    +-- vtterm_devctl()                    [行1102: 通知生成]
            |
            +-- devctl_notify("VT", "BELL", "RING", ...)  [行1116]

vtterm_ioctl() [KDMKTONE/KIOCSOUND]
    |
    +-- vtterm_devctl()                    [行1167: パラメータ付き通知]
            |
            +-- devctl_notify("VT", "BELL", "RING", ...)
```

### データフロー図

```
[入力]                     [処理]                         [出力]

BEL文字 / ioctl -------> vtterm_devctl()              --> devctl キュー
                              |                              |
vt_enable_bell          sbuf: enabled, hushed,          devd(8) 受信
VDF_QUIET_BELL               hz, duration_ms
vw_bell_pitch/duration
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| vt_core.c | `sys/dev/vt/vt_core.c` | ソース | VT コア処理。通知発行元 |
| vt.h | `sys/dev/vt/vt.h` | ヘッダー | VT データ構造定義 |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify() 実装 |
