# Device Attributes (DA)

> Ask the terminal what kind of terminal it is.

- **Sequence:** `CSI Ps c`
- **Defaults:** Ps = 0
- **ECMA-48:** [§8.3.24 DA – Device Attributes, p. 37](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n50/mode/1up)
- **DEC STD 070:** [§4, ch. 5 Device Attributes (Primary), p. 17](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n220/mode/1up)
- **VT220:** [§4.17.1 Device Attributes (DA)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.17.1)
- **VT510:** [DA1—Primary Device Attributes](https://vt100.net/docs/vt510-rm/DA1.html)

With `Ps` left out or `0`, DA asks the terminal to identify itself, and the
terminal answers `CSI ? Ps ; … c`. DEC STD 070 defines what the answer means.
The first parameter is the kind of device and the level of DEC's
architecture it conforms to: 61 to 69 are character-cell displays, so 62 is
one conforming to level 2. The rest name extensions it has, such as 22 for
ANSI color.

With any other `Ps`, ECMA-48 says DA does the opposite: it identifies the
*sender*, with `Ps` as a device type code. A terminal receiving one has not
been asked anything. DEC STD 070 likewise makes only an omitted or zero
parameter a request, and xterm answers only those.

What the terminal says about itself is the host program's choice.
libghostty-vt asks its host and encodes whatever comes back, and the cases
here run with the answers Ghostty gives, describing itself in its source as
a VT220: level 2, with ANSI color. See the [notation](https://control-codes.page/notation/index.html.md) page.

Two DEC extensions ask for more:

- `CSI > c` is secondary DA, the
  [VT510 manual's DA2](https://vt100.net/docs/vt510-rm/DA2.html). The answer
  `CSI > Pp ; Pv ; Pc c` gives the terminal type, the firmware version and
  the ROM cartridge.
- `CSI = c` is tertiary DA,
  [DA3](https://vt100.net/docs/vt510-rm/DA3.html). The answer is a control
  string, `DCS ! | D…D ST`, holding the terminal's unit ID as four
  hexadecimal pairs.

DECID, `ESC Z`, is the VT52-era way of asking the same thing as DA. The VT510
manual says it makes the terminal send its DA answer, and that programs
should use DA instead.

## Validation

### DA-1: Primary attributes

Input, one step per line:

```text
\e[c
```

Expected screen:

```text
|_____|
reply \e[?62;22c
```

### DA-2: With the parameter zero

Input, one step per line:

```text
\e[0c
```

Expected screen:

```text
|_____|
reply \e[?62;22c
```

### DA-3: Secondary attributes

Input, one step per line:

```text
\e[>c
```

Expected screen:

```text
|_____|
reply \e[>1;10;0c
```

### DA-4: Tertiary attributes

Input, one step per line:

```text
\e[=c
```

Expected screen:

```text
|_____|
reply \eP!|00000000\e\\
```

### DA-5: A non-zero parameter is not a request

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e[1c     # identifies the host; asks nothing
```

Expected screen:

```text
|_____|
reply none
```

libghostty-vt answers it as if it were a request. Its DA dispatch in
`stream.zig` chooses primary, secondary or tertiary from the intermediate
byte alone and never looks at the parameter. ECMA-48 makes a non-zero DA an
identification of its sender, DEC STD 070 makes only an omitted or zero
parameter a request, and xterm replies only when the parameter is zero or
left out.

### DA-6: DECID

Input, one step per line:

```text
\eZ
```

Expected screen:

```text
|_____|
reply \e[?62;22c
```

---

This is the Markdown version of <https://control-codes.page/csi/da/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
