(日本語: PROTOCOL.ja.md)
The USB HID protocol that drives the display on the pump head of the CPS DS360 WH liquid cooler. The manufacturer publishes nothing about it, so this document is the result of measuring the real device.
- Analysed: 2026-08-02
- Method: packet capture with USBPcap, then sending crafted reports to the real cooler
- Environment: Windows 11 Pro (26200), behind an AMD USB 3.20 XHCI controller
Nothing here is inferred. Every item was confirmed against real hardware, and anything that stayed uncertain is labelled unverified.
| Field | Value |
|---|---|
| VID / PID | 0x2E3C / 0x0A15 |
| Manufacturer | APALTEK (the actual ODM; PCCooler is the retail brand) |
| Product | LIQUID COOLER DIGITAL DISPLAY - PCC |
| bcdDevice | 0x0200 |
| UsagePage / Usage | 0xFF00 (vendor-defined) / 0x0001 |
| Power | self-powered / 100 mA |
Locate the device path by enumerating the HID class GUID
{4d1e55b2-f16f-11cf-88cb-001111000030}, matching VID/PID, and checking the
product string for LIQUID COOLER before sending.
The device is not exclusively locked. It can be opened with
GENERIC_READ|GENERIC_WRITE while the bundled software is running (measured).
0x2E3C belongs to ARTERY Technology, a microcontroller vendor — it is not specific
to this cooler. APALTEK reuses the VID of the MCU it ships, so unrelated products
answer to the same VID. Always match the product string as well.
| EP | Direction | Type | Size | bInterval |
|---|---|---|---|---|
0x01 |
OUT | Interrupt | 64 | 2 |
0x81 |
IN | Interrupt | 64 | 2 |
Report lengths as seen through the Windows HID API:
| Bytes | |
|---|---|
| OutputReportByteLength | 65 (1 report ID + 64 data) |
| InputReportByteLength | 64 |
| FeatureReportByteLength | 65 |
The 101-byte HID report descriptor declares three channels.
| OUT | IN | Purpose |
|---|---|---|
0x10 |
0x11 |
Unknown. The bundled software does not use it either (unverified) |
0x20 |
0x21 |
Display data (analysed below) |
0xF0 |
0xF1 |
Presumed firmware update. Do not touch (see below) |
F-range report IDs are the conventional home of firmware update channels, and the
bundled binary contains CUpgradeDialog and FtpManager::checkUpdate — traces of an
update feature that fit that reading. A wrong write there could leave the device
unable to boot, so nothing is ever sent to this channel.
Send 65 bytes to OUT endpoint 0x01, every 0.5 s, without stopping.
Offset Value Meaning
─────────────────────────────────────────────────────────────
[0] 0x20 Report ID (fixed)
[1] 0x01 Command: update data (fixed)
[2] 0x00 Unit: 0 = Celsius, 1 = Fahrenheit
[3] 0x00 Blink: 0 = steady, non-zero = blink
[4] 0x00 Unused
[5] 0x00 Unused
[6] value ★ the number shown on the display ★
[7] 0x00 Unused
[8] 0x00 Unused
[9] value Second temperature (not shown on the DS360 WH)
[10]–[64] All 0x00 (unused)
IN endpoint 0x81 returns 64 bytes in response. The content is always the same —
21 01 01 followed by zeros. Nothing beyond an ACK has been established.
- 3½-digit seven-segment LED. The hundreds position is a half-digit that can only show
1 - Displayable range: 0–199
- Carries a degree dot and a red lamp
| Sent | Displayed |
|---|---|
| 0 | 0 |
| 100 | 100 |
| 199 | 199 |
| 200 | 99 (folded as out of range) |
| 255 | 99 |
Never send 200 or above. The display shows something you did not intend. Clamp to 0–199 before sending.
| Value | Behaviour |
|---|---|
| 0 | Celsius |
| 1 | Fahrenheit |
| 2, 3 | No effect (identical to 0; measured) |
Fahrenheit conversion happens on the PC. The device does not convert anything;
[2] only selects how the reading is labelled.
The conversion confirmed by measurement:
F = floor(C * 9 / 5 + 32)
| Celsius | Fahrenheit sent |
|---|---|
| 65 | 149 |
| 64 | 147 |
| 63 | 145 |
| 62 | 143 |
| 55 | 131 |
Fahrenheit readings run to three digits, which lights the half-digit in the hundreds position.
| Value | Behaviour |
|---|---|
| 0 | Steady |
| Non-zero | Blink (regular, roughly a 1 s period) |
1, 2, 4, 8, 16, 64, 128, 255 all produce the same blink (measured). This is a
plain on/off flag, not a speed control or a mode selector.
Setting [4] and [5] to 0xFF changes neither the rate nor the rhythm (measured).
The bundled software sends this byte as zero at all times and never uses the feature.
The display follows 10 ms updates without dropping frames (100 fps equivalent). As long as the 0.5 s watchdog is satisfied, the send interval can be shortened to animate. The OpenDS360 startup sequence is built on this property.
Stop sending and the display goes dark immediately.
- Keep a 0.5 s interval and the reading is completely stable
- A gap of more than about a second blanks the display
- Resuming the stream brings it back
An implementation therefore must not let the 0.5 s send loop lapse. Anyone who implements this without knowing will meet "the display turns off for no reason."
The same behaviour also means blanking can be produced deliberately. For visual
effects, [3] gives a cleaner result than cutting the stream.
| State | How |
|---|---|
| Steady | keep sending with [3]=0 |
| Blinking | keep sending with [3]=1 |
| Dark | stop sending |
Per-segment control is not available. Lighting individual segments or running a
rotation animation cannot be done, because no command exists for it. That conclusion
follows a scan of every channel in the report descriptor and every byte of 0x20.
The red lamp did not respond to any byte, [3] included. It stays lit even when 33 °C
is sent, so it is not driven by a temperature threshold either. It appears to be
decorative or always on (unverified).
C:\Program Files (x86)\DeviceMonitorPcc\DeviceMonitorPcc.exe (V1.0.2.5, built with Qt5)
What reading the binary turned up, and what led to writing a replacement:
- FTP credentials are embedded in plain text in the executable. A plain FTP connection to an external server is attempted at every start (it fails every time, per its own log)
- A debug CRT (
ucrtbased.dll) ships with the release build - The code-signing certificate expired on 2025-02-27 with no sign of renewal
- The logon entry is written to
HKLM\...\Run, a location that requires administrator rights - The About dialog's Hardware and Firmware Version are never requested from the device. They are hardcoded values that do not reflect the hardware
Sensor values are read through HWiNFO32.dll.
- Never let the 0.5 s send loop lapse (watchdog)
- Clamp
[6]to 0–199 - Convert to Fahrenheit on the PC (
floor(C*9/5+32)) - Never send to
0xF0/0xF1 - Do not identify the device by VID/PID alone. Match the product string
LIQUID COOLER - The device is not exclusively locked, so running alongside the bundled software means both processes write in turn and the display flickers. Stop the bundled software while your own is running
The following was not resolved. Findings are welcome.
| Item | Status |
|---|---|
Reports 0x10 / 0x11 |
Purpose unknown. The bundled software does not use them either |
Second temperature [9] |
Not shown on the DS360 WH. Presumably for models with a second readout (unverified) |
| Red lamp | Responded to no byte. Presumably decorative or always on (unverified) |
Reports 0xF0 / 0xF1 |
Presumed firmware update channel. Deliberately left untested |