# Device Attributes (DA)

> Ask the terminal what kind of terminal it is.

- **Sequence:** `CSI Ps c`
- **Defaults:** Ps = 0
- **DECID**, Identify Terminal: `ESC Z`
- **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 a default xterm's answers, as the rest of the cases follow
one. xterm is a VT420 by default, so it answers level 4,
`CSI ? 64 ; 1 ; 2 ; 6 ; 9 ; 15 ; 17 ; 18 ; 21 ; 22 ; 28 c`: 132 columns, a
printer, selective erase, national character sets, technical characters,
terminal state interrogation, user windows, horizontal scrolling, ANSI color and
rectangular editing. Its secondary answer, `CSI > 41 ; 412 ; 0 c`, names a
VT420 and its own patch number. Ghostty itself answers 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.

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | Partly | primary and secondary DA and DECID ([§4.17.1 Device Attributes (DA)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.17.1)); no tertiary DA |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | Yes | [DA1](https://vt100.net/docs/vt510-rm/DA1.html), [DA2](https://vt100.net/docs/vt510-rm/DA2.html), [DA3](https://vt100.net/docs/vt510-rm/DA3.html) |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Yes | answers only an omitted or zero parameter |
| libghostty-vt | [0f171f6](https://github.com/ghostty-org/ghostty/tree/0f171f650a1cbbd6df4a2573b6b0c7de57cc6d90) | Yes | answers from its host; DA-5: also answers a non-zero parameter |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | Partly | lists `ESC [ c` and `ESC [ > c`, no tertiary DA: [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |

## Validation

### DA-1: Primary attributes

Input, one step per line:

```text
\e[c
```

Expected screen:

```text
|_____|
reply \e[?64;1;2;6;9;15;17;18;21;22;28c
```

### DA-2: With the parameter zero

Input, one step per line:

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

Expected screen:

```text
|_____|
reply \e[?64;1;2;6;9;15;17;18;21;22;28c
```

### DA-3: Secondary attributes

Input, one step per line:

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

Expected screen:

```text
|_____|
reply \e[>41;412;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[?64;1;2;6;9;15;17;18;21;22;28c
```

---

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>.
