skywalker-1/gp8psk-driver-analysis.md
Ryan Malloy bbdcb243dc Normalize line endings to LF across entire repository
Apply .gitattributes normalization to convert all CRLF line
endings inherited from Windows-origin source files to Unix LF.
175 files, zero content changes.
2026-02-20 10:55:50 -07:00

10 KiB

Genpix SkyWalker-1 DVB-S Linux Kernel Driver Analysis

Overview

The Genpix GP8PSK driver is a Linux kernel DVB-USB compliant driver (found at drivers/media/usb/dvb-usb/gp8psk.c) that supports multiple Genpix satellite receiver models. The driver communicates with a Cypress FX2 microcontroller via USB vendor control requests to manage DVB-S satellite reception including demodulation, LNB power control, DiSEqC switching, and signal monitoring.


1. VENDOR USB CONTROL COMMANDS (0x80-0x9D)

All vendor commands use USB control transfers with the following pattern:

  • USB Type: USB_TYPE_VENDOR (vendor-specific request)
  • Direction: USB_DIR_IN (device-to-host) or USB_DIR_OUT (host-to-device)
  • Timeout: 2000ms
  • Retry Logic: Up to 3 attempts for IN operations if partial data received
  • Data Buffer: 80 bytes maximum (kernel driver state structure)

Complete Vendor Command Map

Cmd Name Direction wValue wIndex wLength Purpose
0x80 GET_8PSK_CONFIG IN 0x0000 0x0000 1 byte Read device configuration status byte
0x81 SET_8PSK_CONFIG OUT varies 0x0000 0 Set config (STALL - not implemented)
0x82 (reserved) -- -- -- -- STALL - not used
0x83 I2C_WRITE OUT dev_addr reg_addr N bytes Write to I2C device (BCM4500 demod)
0x84 I2C_READ IN dev_addr reg_addr N bytes Read from I2C device (BCM4500 demod)
0x85 ARM_TRANSFER OUT onoff (0/1) 0x0000 0 Start/stop MPEG-2 stream transfer
0x86 TUNE_8PSK OUT 0x0000 0x0000 10 bytes Set tuning parameters
0x87 GET_SIGNAL_STRENGTH IN 0x0000 0x0000 6 bytes Read SNR (signal quality)
0x88 LOAD_BCM4500 OUT 1 (start) 0x0000 0 Initiate BCM4500 firmware download
0x89 BOOT_8PSK IN onoff (0/1) 0x0000 1 byte Power on/off 8PSK demodulator
0x8A START_INTERSIL IN onoff (0/1) 0x0000 1 byte Enable/disable LNB power supply
0x8B SET_LNB_VOLTAGE OUT voltage (0/1) 0x0000 0 Set LNB to 13V (0) or 18V (1)
0x8C SET_22KHZ_TONE OUT onoff (0/1) 0x0000 0 Enable/disable 22 kHz DiSEqC tone
0x8D SEND_DISEQC_COMMAND OUT msg[0] 0x0000 len Send DiSEqC message to dish switch
0x8E SET_DVB_MODE OUT 1 0x0000 0 Enable DVB-S mode (STALL on some revisions)
0x8F (unknown) -- -- -- -- Unknown/internal use
0x90 GET_SIGNAL_LOCK IN 0x0000 0x0000 1 byte Read signal lock status bit
0x91-0x98 (internal use) -- -- -- -- I2C/diagnostic reads
0x99 GET_DEMOD_STATUS (v2.13+) IN 0x0000 0x0000 1 byte Read BCM4500 register 0xF9 via I2C
0x9A INIT_DEMOD (v2.13+) OUT 0x0000 0x0000 0 Trigger demodulator re-init (up to 3 attempts)
0x9B (reserved) -- -- -- -- STALL - not used
0x9C DELAY_COMMAND (v2.13+) OUT delay_param 0x0000 0 Perform tuning/acquisition delay with polling
0x9D CW3K_INIT OUT onoff (0/1) 0x0000 0 Initialize SkyWalker CW3K model

Configuration Status Byte (GET_8PSK_CONFIG - 0x80)

The returned byte is a bit-mapped status register:

Bit 0 (0x01): bm8pskStarted       - Device booted and running
Bit 1 (0x02): bm8pskFW_Loaded     - BCM4500 firmware loaded
Bit 2 (0x04): bmIntersilOn        - LNB power supply enabled
Bit 3 (0x08): bmDVBmode           - DVB mode enabled
Bit 4 (0x10): bm22kHz             - 22 kHz tone active
Bit 5 (0x20): bmSEL18V            - 18V LNB voltage selected (else 13V)
Bit 6 (0x40): bmDCtuned           - DC offset tuning complete
Bit 7 (0x80): bmArmed             - MPEG-2 stream transfer armed

2. FIRMWARE LOADING SEQUENCE

Two-Stage Firmware Loading

The device requires two separate firmware files:

Stage 1: FX2 RAM Code (Bootloader Phase)

  • File: dvb-usb-gp8psk-01.fw
  • Purpose: Cypress FX2 microcontroller firmware
  • When: Loaded automatically by DVB-USB framework during device enumeration (cold-to-warm boot transition)
  • How: Standard USB firmware upload via control endpoint (0xA0 vendor request to CPUCS)
  • Device Mode: Cold boot (VID 0x09C0, PID 0x0200)

Stage 2: BCM4500 Demodulator Firmware (Tuner Phase)

  • File: dvb-usb-gp8psk-02.fw
  • Purpose: Broadcom BCM4500 DVB-S demodulator chip firmware
  • When: Loaded after device power-on via LOAD_BCM4500 command
  • How: Custom binary protocol via USB control transfers
  • Conditions: Only for Rev.1 Warm devices; Rev.2 and SkyWalker have firmware burned in ROM

BCM4500 Firmware Loading Protocol

// Step 1: Initiate load
gp8psk_usb_out_op(device, LOAD_BCM4500, 1, 0, NULL, 0);  // 0x88 cmd, wValue=1

// Step 2: Download firmware chunks
// Format: [chunk_length] [data...] repeated, terminated by 0xFF
ptr = fw_data;
while (ptr[0] != 0xFF) {
    chunk_size = ptr[0] + 4;  // length byte + 3 extra bytes
    if (chunk_size > 64) ERROR("chunk too large");
    buf = copy chunk_size bytes from ptr;
    usb_control_msg(device, USB_SNDCTRLPIPE, 0, ..., buf, chunk_size, 2000ms);
    ptr += chunk_size;
}

Boot Sequence Flow (Power-On)

1. Read device config (GET_8PSK_CONFIG - 0x80)
   +-- Check bit 0: Device started?

2. If not started:
   +-- Boot device (BOOT_8PSK - 0x89, wValue=1)
   +-- Get firmware version (via 0x0B: FW_VERSION_READ)

3. If firmware not loaded (check bit 1):
   +-- Load BCM4500 firmware (LOAD_BCM4500 - 0x88)

4. If LNB not powered (check bit 2):
   +-- Enable LNB supply (START_INTERSIL - 0x8A, wValue=1)

5. Set DVB mode (on some revisions):
   +-- SET_DVB_MODE - 0x8E, wValue=1

6. Abort any pending MPEG transfer:
   +-- ARM_TRANSFER - 0x85, wValue=0 (cancel)

7. Ready for tuning/reception

3. TUNING AND DEMODULATION FLOW

Frequency Tuning (TUNE_8PSK - 0x86)

The tuning command transmits a 10-byte parameter structure:

Bytes 0-3:   Symbol Rate (Little-Endian 32-bit, in sps)
Bytes 4-7:   Tuner Frequency (Little-Endian 32-bit, in kHz)
Byte 8:      Modulation Type (see table below)
Byte 9:      Inner FEC Rate / reserved

Modulation Types

ADV_MOD_DVB_QPSK      = 0   // DVB-S standard QPSK
ADV_MOD_TURBO_QPSK    = 1   // Turbo QPSK
ADV_MOD_TURBO_8PSK    = 2   // Turbo 8PSK (Trellis)
ADV_MOD_TURBO_16QAM   = 3   // Turbo 16QAM
ADV_MOD_DCII_C_QPSK   = 4   // Digicipher II Combo
ADV_MOD_DCII_I_QPSK   = 5   // Digicipher II I-stream (split)
ADV_MOD_DCII_Q_QPSK   = 6   // Digicipher II Q-stream (split)
ADV_MOD_DCII_C_OQPSK  = 7   // Digicipher II offset QPSK
ADV_MOD_DSS_QPSK      = 8   // DSS/DIRECTV QPSK
ADV_MOD_DVB_BPSK      = 9   // DVB-S BPSK

Complete Tuning Sequence

1. Configure LNB voltage based on polarization:
   H/CIRCULAR_L -> 18V (SET_LNB_VOLTAGE - 0x8B, wValue=1)
   V/CIRCULAR_R -> 13V (SET_LNB_VOLTAGE - 0x8B, wValue=0)

2. Set 22 kHz tone:
   SET_22KHZ_TONE - 0x8C, wValue=0/1

3. Send DiSEqC switch command if needed (see section 4)

4. Send tuning command:
   TUNE_8PSK - 0x86, 10-byte parameter buffer

5. Poll for lock:
   GET_SIGNAL_LOCK - 0x90 (returns 1 byte, non-zero = locked)

Signal Quality Monitoring

GET_SIGNAL_STRENGTH (0x87) returns 6-byte buffer:

Bytes 0-1:  SNR value (LE 16-bit, dBu*256 units)
Bytes 2-5:  Reserved/diagnostics

SNR scaling: snr * 17 maps to 0-65535 (100% at SNR >= 0x0F00)


4. DiSEqC COMMAND HANDLING (0x8D)

Tone Burst (Mini DiSEqC)

// For legacy 2-way switches
gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND,
                  burst_value,  // SEC_MINI_A=0x00 or SEC_MINI_B=0x01
                  0, NULL, 0);

Full DiSEqC Message (3-6 bytes)

// Standard DiSEqC 1.0/1.1/1.2 messages
gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND,
                  msg[0],        // Framing byte as wValue
                  0,
                  msg,           // Full message buffer
                  msg_len);      // 3-6 bytes

Common framing bytes: 0xE0 (broadcast, no reply), 0xE1 (addressed, no reply)


5. DEVICE TABLE AND USB IDS

Kernel Module Aliases (Linux 6.16.5)

usb:v09C0p0200  - Rev.1 Cold boot (requires FX2 firmware upload)
usb:v09C0p0201  - Rev.1 Warm (requires BCM4500 FW via 0x88)
usb:v09C0p0202  - Rev.2 (BCM4500 in ROM)
usb:v09C0p0203  - SkyWalker-1 (PID confirmed on actual hardware)
usb:v09C0p0204  - SkyWalker-1 (alternate revision)
usb:v09C0p0206  - SkyWalker CW3K (requires CW3K_INIT 0x9D)

Note: PID 0x0205 (SkyWalker-2) is absent from the 6.16.5 kernel build. Note: PID 0x0203 was not in earlier kernel versions (e.g., v6.6.1).

Device Properties

gp8psk_properties {
    usb_ctrl = CYPRESS_FX2;
    firmware = "dvb-usb-gp8psk-01.fw";
    num_adapters = 1;
    endpoint = 0x82 (IN bulk);
    stream = USB_BULK;
    count = 7 URBs;
    buffersize = 8192 bytes per URB;
    generic_bulk_ctrl_endpoint = 0x01;
}

6. CORRELATION: KERNEL DRIVER vs FIRMWARE ANALYSIS

Commands Used by Kernel Driver

Command Driver Uses v2.06 FW v2.13 FW Rev.2 FW
0x80 GET_8PSK_CONFIG Boot check OK OK OK
0x83 I2C_WRITE BCM4500 reg writes OK OK OK
0x84 I2C_READ BCM4500 reg reads OK OK OK
0x85 ARM_TRANSFER Stream start/stop OK OK OK
0x86 TUNE_8PSK Frequency tuning OK OK OK
0x87 GET_SIGNAL_STRENGTH SNR readback OK Changed OK
0x88 LOAD_BCM4500 BCM4500 FW load STALL STALL STALL
0x89 BOOT_8PSK Power on/off OK OK OK
0x8A START_INTERSIL LNB power OK OK OK
0x8B SET_LNB_VOLTAGE 13V/18V OK OK OK
0x8C SET_22KHZ_TONE Tone control OK OK OK
0x8D SEND_DISEQC DiSEqC messages OK (GPIO) OK (I2C) OK
0x90 GET_SIGNAL_LOCK Lock status OK OK OK
0x9D CW3K_INIT CW3K only N/A v2.13 only N/A

Key Finding: LOAD_BCM4500 (0x88) STALLs

Command 0x88 routes to the STALL handler in all extracted firmware versions. The kernel driver only sends this command for Rev.1 Warm (PID 0x0201) devices, after checking that bm8pskFW_Loaded (bit 1) is NOT set. On Rev.2/SkyWalker hardware, this bit is already set at boot (BCM4500 firmware in ROM), so the driver never attempts the load. The STALL is a safety net.


Sources

  • Linux kernel 6.16.5 dvb-usb-gp8psk module (installed on analysis system)
  • Linux kernel source: drivers/media/usb/dvb-usb/gp8psk.c, gp8psk.h, gp8psk-fe.c
  • Windows BDA driver source: SkyWalker1_Final_Release/Include/SkyWalker1Control.h
  • Firmware reverse engineering via Ghidra (ports 8193-8197)