> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zerokeyusb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# USB Utilities

> Keyboard emulation, serial commands, and backup/restore over the composite USB interface.

## Dual USB personality

ZeroKeyUSB operates as a **composite USB Full-Speed device** exposing two interfaces simultaneously:

```mermaid theme={null}
graph LR
    USB["USB-C Connector"] --> COMP["Composite USB Device"]
    COMP --> HID["HID Keyboard<br/>Class 0x03"]
    COMP --> CDC["CDC Serial<br/>115200 bps"]
    
    HID --> TYPE["Types credentials<br/>to host"]
    CDC --> CMD["Backup, restore,<br/>time sync"]
    
    style USB fill:#dbeafe,stroke:#2563eb,color:#000
    style HID fill:#bbf7d0,stroke:#16a34a,color:#000
    style CDC fill:#fef3c7,stroke:#d97706,color:#000
```

Both interfaces remain active after boot, but CDC commands that modify data require PIN unlock + on-device authorization.

***

## Keyboard output engine

The firmware supports **9 keyboard layouts** stored as compiled keyboard maps:

| Code    | Layout                         |
| ------- | ------------------------------ |
| `EN-US` | United States QWERTY (default) |
| `DA-DK` | Danish                         |
| `DE-DE` | German                         |
| `ES-ES` | Spanish                        |
| `FR-FR` | French                         |
| `HU-HU` | Hungarian                      |
| `IT-IT` | Italian                        |
| `PT-PT` | Portuguese                     |
| `SV-SE` | Swedish                        |

The active layout is stored in EEPROM at `0x003E` and can be changed from **Settings → Keyboard** or during the setup wizard.

### Typing sequence

When you tap **Center** on the credential main screen, ZeroKeyUSB types:

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Device
    participant Host as Host Computer

    User->>Device: Tap Center on credential
    Device->>Host: Type username (char by char)
    Device->>Host: Send TAB key
    Device->>Host: Type password (char by char)
    Note over Device,Host: Each character sent as<br/>USB HID keypress + release
```

The typing engine in `zerokey-utils.cpp` converts each ASCII character to the appropriate HID keycode using the selected keyboard layout library.

***

## Serial command protocol

The CDC channel communicates at **115200 bps** using simple ASCII lines. Commands are processed by `handleIncomingHostRequests()` in `zerokey-io.cpp`.

| Command         | Direction     | Pre-condition            | Description                                                     |
| --------------- | ------------- | ------------------------ | --------------------------------------------------------------- |
| `EXPORT` or `R` | Host → Device | PIN unlocked             | Initiates credential export. Device shows authorization prompt. |
| `IMPORT`        | Host → Device | PIN unlocked             | Initiates credential import. Device shows authorization prompt. |
| `<epoch>`       | Host → Device | Device showing `REQTIME` | Sends Unix epoch timestamp for TOTP synchronization.            |

### Export data format

Each credential is sent as a CSV line:

```
slotIndex,siteName,userName,password[,totpSecret]
```

* The TOTP field is optional and only included if the slot has a 2FA secret.
* The first line sent is the total number of slots (`62`).
* Example: `0,github.com,alice,MyP@ss123,JBSWY3DPEHPK3PXP`

### Import data format

Same CSV format. The host sends:

1. The total number of records (integer).
2. One line per record: `slotIndex,site,user,pass[,totpSecret]`.

The device encrypts each field with AES-128 CBC and writes to the corresponding EEPROM slot.

***

## Time synchronization

TOTP codes require accurate time. Since ZeroKeyUSB has **no hardware RTC**, time is tracked using `millis()` drift from a synced epoch.

```mermaid theme={null}
sequenceDiagram
    participant Device
    participant Host

    Device->>Host: "REQTIME" (via SerialUSB)
    Note over Device: Shows "Time not set"<br/>on OLED
    Host->>Device: "1714328400" (Unix epoch)
    Device->>Device: syncTotpEpoch(epoch)
    Device->>Device: Save to EEPROM 0x0040
    Note over Device: TOTP codes now available
```

* The epoch value must be between `946684800` (2000-01-01) and `4102444800` (2099-12-31).
* The saved epoch persists across power cycles in EEPROM at `0x0040–0x0047`.
* On each boot, the last saved epoch is loaded and `millis()` tracking resumes from that point.
* Drift accumulates over time; long sessions or frequent unplugging may require re-sync.

***

## Bootloader entry

From **Menu → Danger Zone → Bootloader Mode**, the firmware:

1. Writes `0xF01669EF` to SRAM address `0x20007FFC` (the double-reset magic word).
2. Calls `NVIC_SystemReset()`.
3. The bootloader sees the magic word and stays in USB-CDC DFU mode for firmware flashing.

This allows firmware updates without physical access to SWD pogo pins.

***

## Serial security model

* **Before PIN unlock:** `EXPORT` and `IMPORT` commands are rejected with `ERR LOCKED`.
* **After PIN unlock:** commands are accepted but require **on-device authorization** (long-press Center) before any data transfer begins.
* **During transfer:** the device shows a progress screen and rejects new commands with `ERR BUSY`.
* **No hidden commands:** the serial protocol has no debug, dump, or diagnostic commands in production firmware.

<Note>
  All serial communication is plaintext. There is no encryption layer on the CDC channel. Treat the USB connection as a direct wire to the device's internals.
</Note>
