> For the complete documentation index, see [llms.txt](https://manual.simhubdash.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://manual.simhubdash.com/device-definition-authoring/device-communication-protocols.md).

# Device communication protocols

Simhub can communicate in various ways to your devices, some protocols are pre implemented,\
No matter the protocol they all need you to be able to assign to your MCU a proper **PID/VID you own**.

## SimHub Standard Serial protocol

The most universal protocol, it can be implemented on any device with just a CDC either by using the [Standard Serial Firmware Builder](/standard-serial-firmware-builder/readme-1.md) (for atmega32u4) or copying the existing protocol

## Screen pass-through

Both USBD480NX and Vocore offer to drive leds through the screen. In such case you can use this protocol to instruct simhub to use the screen for the LEDs control.

## SimHub Standard HID protocol

When things will get more serious you might want to switch a proper HID implementation,

Simhub can identify the HID interface based on the HID Usage and usage page. The report ID and report length can be specified.

Make sure to properly include the report in your device HID descriptor, descriptors not specifying the report id won't work.

To be able to support multiple device instance, make sure your device exposes an unique HID serial number.

#### HID Report Format

The SimHub Standard HID protocol can expose separate reports for LEDs, motors and fans. Each report uses its own report ID and can use the same HID report length configured for the device.

Shorter or longer reports (for example 32, 64 or 128 bytes) can be used depending on the microcontroller capabilities. If the configured report length is too short to carry all channels, SimHub sends multiple packets using the start index, affected channel count and final packet flag.

### LED report

The LED report is used to update RGB LEDs efficiently. The default report ID used by the standard firmware builder is `0x68`.

| Byte  | Description                                                                                                                                                            | Example value    |
| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| 1     | **LED Report ID**                                                                                                                                                      | `0x68`           |
| 2     | **Start LED index**                                                                                                                                                    | `0x00`           |
| 3     | **Affected LED count**                                                                                                                                                 | `0x14` (20)      |
| 4     | **Draw flag**: `0` while more LED packets are expected, `1` for the last LED packet, `2` for the optional on connect report, `3` for the optional on disconnect report | `0x00`           |
| 5-7   | **LED #1**: R, G, B                                                                                                                                                    | `0xFF 0xFF 0xFF` |
| 8-10  | **LED #2**: R, G, B                                                                                                                                                    | `0xFF 0xFF 0xFF` |
| ...   | **Next LEDs**                                                                                                                                                          | `...`            |
| 62-64 | **Last LED in a 64-byte report**: R, G, B                                                                                                                              | `0xFF 0xFF 0xFF` |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each LED uses 3 bytes, one packet can carry up to 20 LEDs.

The draw flag allows physical LEDs, such as WS2812B LEDs, to be refreshed only once per full frame. The optional `on connect` and `on disconnect` reports use the LED report ID and set the draw flag to `2` or `3`; all other data is set to zero.

{% hint style="info" %}
Warning the `on disconnect` report can't be guaranteed in case of process being killed or usb issue causing a disconnect for instance. Simhub sends a keep alive "draw" every 5 seconds even if nothing has changed. Using an internal firmware timeout of 6s would be relevant in cases of automations to be triggered after a software disconnect.
{% endhint %}

### Motor report

{% hint style="warning" %}
Motor HID reports are intended for the next SimHub device descriptor/standard HID implementation and are not available in current public SimHub releases yet.
{% endhint %}

The motor report carries one gain value and one frequency value per motor. The default report ID used by the standard firmware builder is `0x6A`.

| Byte  | Description                                                                  | Example value |
| ----- | ---------------------------------------------------------------------------- | ------------- |
| 1     | **Motor Report ID**                                                          | `0x6A`        |
| 2     | **Start motor index**                                                        | `0x00`        |
| 3     | **Affected motor count**                                                     | `0x02`        |
| 4     | **Final packet flag**: `1` when this is the last motor packet, otherwise `0` | `0x01`        |
| 5-6   | **Motor #1 gain**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`     | `0xFF 0xFF`   |
| 7-8   | **Motor #1 frequency**, unsigned 16-bit big-endian                           | `0x00 0x3C`   |
| 9-10  | **Motor #2 gain**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`     | `0x80 0x00`   |
| 11-12 | **Motor #2 frequency**, unsigned 16-bit big-endian                           | `0x00 0x78`   |
| ...   | **Next motors**                                                              | `...`         |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each motor uses 4 bytes, one packet can carry up to 15 motors at the communication level. The current SimHub device descriptor implementation limits motor devices to 8 motors.

If the device descriptor does not expose frequency support for motors, firmware can ignore the frequency field.

### Fan report

{% hint style="warning" %}
Fan HID reports are intended for the next SimHub device descriptor/standard HID implementation and are not available in current public SimHub releases yet.
{% endhint %}

The fan report carries one unsigned 16-bit speed value per fan. The default report ID used by the standard firmware builder is `0x69`.

| Byte | Description                                                                | Example value |
| ---- | -------------------------------------------------------------------------- | ------------- |
| 1    | **Fan Report ID**                                                          | `0x69`        |
| 2    | **Start fan index**                                                        | `0x00`        |
| 3    | **Affected fan count**                                                     | `0x02`        |
| 4    | **Final packet flag**: `1` when this is the last fan packet, otherwise `0` | `0x01`        |
| 5-6  | **Fan #1 speed**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`    | `0xFF 0xFF`   |
| 7-8  | **Fan #2 speed**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`    | `0x80 0x00`   |
| ...  | **Next fans**                                                              | `...`         |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each fan uses 2 bytes, one packet can carry up to 30 fans at the communication level. The current SimHub device descriptor implementation limits fan devices to 3 fans.

### Examples

Example 1 - Updating 2 LEDs

*Update the first 2 LEDs (LED #0 to #1):*

```
0x68  0x00  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ... 00
```

Example 2 - Updating 22 LEDs (split across packets)

*Update the first 20 LEDs (LED #0 to #19):*

```
0x68  0x00  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the last 2 LEDs (LED #20 to #21):*

```
0x68  0x14  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ...
```

Example 3 - Updating 42 LEDs (split across packets)

*Update the first 20 LEDs (LED #0 to #19):*

```
0x68  0x00  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the next 20 LEDs (LED #20 to #39):*

```
0x68  0x14  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the last 2 LEDs (LED #40 to #41):*

```
0x68  0x28  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ...
```

Example 4 - Optional on connect report

*Sends a draw byte set to `2` on connection.*

```
0x68  0x00  0x00  0x02  00 00 00  00 00 00  ...  00 00 00
```

Example 5 - Optional on disconnect report

*Sends a draw byte set to `3` before disconnecting.*

```
0x68  0x00  0x00  0x03  00 00 00  00 00 00  ...  00 00 00
```

Example 6 - Updating 2 motors

*Update motor #0 at full gain / 60 Hz and motor #1 at half gain / 120 Hz:*

```
0x6A  0x00  0x02  0x01  FF FF  00 3C  80 00  00 78  00 00 ... 00
```

Example 7 - Updating 8 motors

*Update the currently supported maximum of 8 motors in one 64-byte report:*

```
0x6A  0x00  0x08  0x01  FF FF  00 3C  FF FF  00 3C  ...  FF FF  00 3C  00 00 ... 00
```

Example 8 - Updating 2 fans

*Update fan #0 to full speed and fan #1 to half speed:*

```
0x69  0x00  0x02  0x01  FF FF  80 00  00 00 ... 00
```

Example 9 - Updating 3 fans

*Update the currently supported maximum of 3 fans in one 64-byte report:*

```
0x69  0x00  0x03  0x01  FF FF  80 00  40 00  00 00 ... 00
```
