skywalker-1/vendor-commands-unknown.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

20 KiB

Genpix SkyWalker-1 Vendor Commands: Full Decode of "Unknown" Commands

Sources

  • Firmware disassembly via Ghidra MCP: v2.06 (port 8193), v2.13 FW1 (port 8194), Rev.2 v2.10.4 (port 8197)
  • Linux kernel gp8psk-fe.h (kernel 4.9.227 and 6.18.6) -- provides definitive names for 0x8F, 0x92, 0x93, 0x94, 0x95
  • Linux kernel gp8psk.c and gp8psk-fe.c -- shows driver usage
  • Windows driver SkyWalker1Control.h -- confirms 0x8F, 0x93, 0x94

Jump Table Corrections

The original addresses for Rev.2 were shifted by one command index. The corrected jump table targets (decoded from AJMP opcodes at CODE:0x0076) are:

Cmd v2.06 (8193) v2.13 (8194) Rev.2 (8197)
0x8F 0x01FC 0x021E 0x0208
0x90 0x020B 0x022D 0x0217
0x91 0x022C 0x024E 0x0238
0x92 0x024A 0x026C 0x0256
0x93 0x026F 0x0293 0x027D
0x94 0x01B9 0x01DB 0x01C5
0x95 0x02DF 0x0303 0x02ED
0x96 0x02B4 0x02D8 0x02C2
0x97 0x02C1 0x02E5 0x02CF
0x98 0x02CB 0x02EF 0x02D9

Note: v2.06 and v2.13 have 30 jump table entries (0x80-0x9D, range check < 0x1E). Rev.2 has only 27 entries (0x80-0x9A, range check < 0x1B). Commands 0x9B-0x9D do not exist on Rev.2 hardware.


Command 0x8F: SET_DN_SWITCH

Named by: Linux kernel gp8psk-fe.h, Windows driver SkyWalker1Control.h

Field Value
Direction OUT (host-to-device)
wValue Switch command byte (7 bits, LSB-first)
wIndex 0x0000
wLength 0 (no data phase)
Purpose Send legacy Dish Network switch command via GPIO bit-bang

Firmware Behavior

All three versions implement the same algorithm:

  1. Read wValueL from SETUPDAT[2] (0xE6BA)
  2. Store value, then call a GPIO bit-bang subroutine:
    • Assert P0.4 high (start pulse)
    • Delay ~32 cycles
    • Deassert P0.4
    • Delay ~8 cycles
    • Loop 7 times, shifting out each bit LSB-first via P0.4
    • Between bits: delay ~8 cycles
  3. ACK with EP0BCL = 0 (no data returned)

Subroutine Addresses

Version Handler Bit-bang Routine Delay Routine
v2.06 0x01FC 0x1F04 0x1DFB
v2.13 0x021E 0x1ECD 0x14B9
Rev.2 0x0208 0x1CE6 0x1BDA

Linux Driver Usage

// gp8psk-fe.c: gp8psk_fe_send_legacy_dish_cmd()
u8 cmd = sw_cmd & 0x7f;
st->ops->out(st->priv, SET_DN_SWITCH, cmd, 0, NULL, 0);
// Then sets LNB voltage based on bit 7 of sw_cmd
st->ops->out(st->priv, SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), 0, NULL, 0);

This is the dishnetwork_send_legacy_command callback in the DVB frontend ops. The 7-bit command value is a legacy Dish Network satellite switch protocol word, bit-banged on GPIO P0.4 with specific timing. The 8th bit (0x80) of the original command selects LNB voltage (13V or 18V) and is sent separately.

Cross-Version Differences

None. All three versions use identical logic (same GPIO pin P0.4, same timing, same 7-bit protocol). Only the subroutine addresses differ due to code relocation.


Command 0x91: I2C_ADDR_ADJUST (internal debug)

Not named in any driver header. This command is not used by either the Linux or Windows driver.

Field Value
Direction IN (device-to-host)
wValue 0 = decrement, non-zero = increment
wIndex 0x0000
wLength 1 byte
Returns Current value of internal counter byte
Purpose Increment/decrement an internal IRAM counter; return its value

Firmware Behavior

if wValueL != 0:
    IRAM[counter]++
else:
    IRAM[counter]--
EP0BUF[0] = IRAM[counter]
EP0BCL = 1

Counter IRAM Addresses

Version IRAM Address
v2.06 0x66
v2.13 0x18
Rev.2 0x18

Purpose

This appears to be a diagnostic/debug command for adjusting an internal pointer or counter, possibly related to I2C bus addressing or tuner register indexing. The counter is used by other internal routines but is not exposed through any standard driver interface. The name "I2C_ADDR_ADJUST" is inferred from its proximity to I2C commands and the inc/dec readback pattern.

Cross-Version Differences

  • v2.06 uses IRAM address 0x66; v2.13 and Rev.2 use 0x18
  • Logic is otherwise identical

Command 0x92: GET_FW_VERS

Named by: Linux kernel gp8psk-fe.h (#define GET_FW_VERS 0x92)

Field Value
Direction IN (device-to-host)
wValue 0x0000
wIndex 0x0000
wLength 6 bytes
Returns Firmware version and build date (6 bytes, fixed per firmware build)
Purpose Read firmware version identifier

Data Format

Byte 0: Version minor-minor (fw_vers[0])
Byte 1: Version minor       (fw_vers[1])
Byte 2: Version major       (fw_vers[2])
Byte 3: Build day
Byte 4: Build month
Byte 5: Build year (offset from 2000)

Full version number: fw_vers[2] << 16 | fw_vers[1] << 8 | fw_vers[0] Build date: (2000 + fw_vers[5]) / fw_vers[4] / fw_vers[3]

Values Per Firmware

Version Raw Bytes Version Build Date FW_VERS macro
v2.06 04 06 02 0D 07 07 2.06.04 2007-07-13 0x020604 (= GP8PSK_FW_REV1)
v2.13 01 0D 02 0C 03 0A 2.13.01 2010-03-12 0x020D01
Rev.2 04 0A 02 0C 03 0A 2.10.04 2010-03-12 0x020A04 (>= GP8PSK_FW_REV2)

Linux Driver Usage

// gp8psk.c: gp8psk_get_fw_version()
gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6);

// gp8psk.c: gp8psk_info() -- prints on boot:
// "FW Version = 2.06.4 (0x20604)  Build 2007/07/13"

// gp8psk-fe.h: Used for hardware revision detection:
#define GP8PSK_FW_REV1  0x020604
#define GP8PSK_FW_REV2  0x020704
// if GP8PSK_FW_VERS(fw) >= GP8PSK_FW_REV2 -> Rev.2 hardware

Firmware Implementation

The handler writes 6 hardcoded immediate values to EP0BUF[0..5] and sets EP0BCL = 6. There is no I2C or EEPROM access -- the version bytes are compiled directly into the firmware binary.

Cross-Version Differences

Only the embedded constant values differ (they reflect each firmware's own version). The handler structure is identical across all three versions.


Command 0x93: GET_SERIAL_NUMBER

Named by: Linux kernel gp8psk-fe.h, Windows driver SkyWalker1Control.h

Field Value
Direction IN (device-to-host)
wValue 0x0000
wIndex 0x0000
wLength 4 bytes
Returns 4-byte device serial number read from I2C EEPROM
Purpose Read unique device serial number from onboard EEPROM

Firmware Behavior

  1. Call EEPROM initialization routine (sets up I2C for device address 0x51)
  2. Read byte at EEPROM bit-offset 0x08 -> EP0BUF[0]
  3. Read byte at EEPROM bit-offset 0x10 -> EP0BUF[1]
  4. Read byte at EEPROM bit-offset 0x18 -> EP0BUF[2]
  5. Read byte at EEPROM bit-offset (from init) -> EP0BUF[3]
  6. Set EP0BCL = 4

The I2C EEPROM at address 0x51 (7-bit) is a standard 24Cxx-family serial EEPROM. The serial number bytes are extracted at 8-bit intervals using a shift/rotate extraction routine.

Subroutine Addresses

Version Handler EEPROM Init Byte Extract
v2.06 0x026F 0x1DA8 0x077C
v2.13 0x0293 0x1D4B 0x078A
Rev.2 0x027D 0x1A50 0x0798

Cross-Version Differences

None in behavior. The EEPROM device address (0x51) and bit-offset scheme are identical. Only subroutine addresses differ.


Command 0x94: USE_EXTRA_VOLT

Named by: Linux kernel gp8psk-fe.h, Windows driver SkyWalker1Control.h

Field Value
Direction OUT (host-to-device) in v2.06/v2.13; OUT with 1-byte ACK in Rev.2
wValue 0 = normal voltage (13V/18V), non-zero = high voltage (14V/19V)
wIndex 0x0000
wLength 0 (v2.06/v2.13); 1 byte returned in Rev.2
Purpose Enable/disable +1V LNB voltage boost for long cable runs

Firmware Behavior

  1. Read wValueL from SETUPDAT[2]
  2. Compute carry flag: CY = (wValueL >= 1) via ADD A,#0xFF
  3. Store carry to a bit-addressable IRAM flag
  4. Call LNB voltage apply routine:
    • If flag set: write 0x6A to XRAM 0xE0B6 (LNB control register)
    • If flag clear: write 0x62 to XRAM 0xE0B6
  5. ACK (v2.06/v2.13: EP0BCL=0; Rev.2: returns 1 byte with result)

The values 0x6A and 0x62 differ in bit 3 (0x08), which controls the extra voltage boost on the LNB power regulator IC. The register at XRAM 0xE0B6 is a hardware control register in the FX2's XRAM-mapped I/O space.

Flag Bit Addresses

Version Bit Address IRAM Byte.Bit
v2.06 bit 0x07 byte 0x20, bit 7
v2.13 bit 0x00 byte 0x20, bit 0
Rev.2 bit 0x04 byte 0x20, bit 4

Subroutine Addresses

Version Handler Voltage Apply
v2.06 0x01B9 0x2481
v2.13 0x01DB 0x23BF
Rev.2 0x01C5 0x21F5

Linux Driver Usage

// gp8psk-fe.c: gp8psk_fe_enable_high_lnb_voltage()
// Mapped to .enable_high_lnb_voltage frontend ops callback
st->ops->out(st->priv, USE_EXTRA_VOLT, onoff, 0, NULL, 0);

Cross-Version Differences

  • v2.06/v2.13: Pure OUT command (EP0BCL=0, no data returned)
  • Rev.2: Returns 1 byte (carry result from the voltage apply subroutine), making it partially an IN command. The Linux driver sends it as OUT and ignores any returned data, so this is backward-compatible.
  • The bit-addressable flag location changes between versions but the functional behavior is identical.

Command 0x95: GET_FPGA_VERS

Named by: Linux kernel gp8psk-fe.h (#define GET_FPGA_VERS 0x95)

Field Value
Direction IN (device-to-host)
wValue 0x0000
wIndex 0x0000
wLength 1 byte (v2.13/Rev.2); 2 bytes (v2.06)
Returns EEPROM-stored hardware/FPGA revision identifier
Purpose Read hardware platform identifier from onboard EEPROM

Firmware Behavior

All versions read from the I2C EEPROM at device address 0x51, but the EEPROM offset and return size differ:

v2.06:

  1. Call EEPROM read at offset 0x31, read 2 bytes
  2. Combine into 16-bit value (R7:R6)
  3. Return 2 bytes in EP0BUF[0..1]

v2.13 and Rev.2:

  1. Call EEPROM read at offset 0x00, read 2 bytes
  2. Compute a combined value
  3. Return 1 byte in EP0BUF[0]

Subroutine Addresses

Version Handler EEPROM Read
v2.06 0x02DF 0x11DD
v2.13 0x0303 0x21AE
Rev.2 0x02ED 0x0FDD

Linux Driver Usage

// gp8psk.c: gp8psk_get_fpga_version()
gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, &fpga_vers, 1);

// gp8psk.c: gp8psk_info() -- prints on boot:
// "FPGA Version = %i"

Despite the name "FPGA," this reads a version/ID byte from the I2C EEPROM. On these devices there is no separate FPGA -- the name is a legacy artifact from the Genpix product line where some models had an FPGA for signal processing. Here it returns the EEPROM-stored hardware platform identifier.

Cross-Version Differences

  • v2.06: Reads EEPROM offset 0x31, returns 2 bytes. The Linux driver only requests 1 byte, so it gets EP0BUF[0] (low byte of the 16-bit value).
  • v2.13/Rev.2: Reads EEPROM offset 0x00, returns 1 byte. This is a cleaner implementation that matches what the driver actually requests.
  • The change from offset 0x31 to offset 0x00 suggests the EEPROM layout was reorganized between Rev.1 and Rev.2 hardware.

Command 0x96: SET_LNB_GPIO_MODE (internal/debug)

Not named in any driver header. This command is not used by either the Linux or Windows driver.

Field Value
Direction OUT (host-to-device)
wValue 0 = default mode, non-zero = extra-volt pin mapping
wIndex 0x0000
wLength 0 (no data phase)
Purpose Configure LNB power supply GPIO output enable pins

Firmware Behavior

  1. Read wValueL, compute carry flag (same pattern as USE_EXTRA_VOLT)
  2. Store flag to bit-addressable IRAM location
  3. Call GPIO configuration routine:

If flag set (v2.06/v2.13):

IOB = (IOB & 0xF7) | 0x06    ; clear IOB.3, set IOB.2 and IOB.1
OEB = 0xFE                    ; enable IOB[7:1] as outputs, IOB.0 as input

If flag clear (v2.06/v2.13):

OEB = 0xF0                    ; enable IOB[7:4] as outputs, IOB[3:0] as inputs

Flag Bit Addresses

Version Bit Address
v2.06 bit 0x07
v2.13 bit 0x04
Rev.2 bit 0x06

Subroutine Addresses

Version Handler GPIO Config
v2.06 0x02B4 0x2406
v2.13 0x02D8 0x2344
Rev.2 0x02C2 0x20F9

Cross-Version Differences

  • v2.06/v2.13: Controls Port B (IOB/OEB) pins only. Clears IOB.3, sets IOB.2 and IOB.1 for voltage mode.
  • Rev.2: Uses different GPIO pins reflecting the Rev.2 PCB layout:
    • Clears IOB.4 (instead of IOB.3)
    • Sets OEB with IOB.4 enabled
    • Additionally sets Port A pins: P0.6 and P0.0 (via ORL P0, #0x41 and ORL OEA, #0x41)
    • Default mode: OEB = 0xE7, OEA = 0x9E

This command configures the GPIO output enable registers that control the LNB voltage regulator hardware. It works in conjunction with USE_EXTRA_VOLT (0x94) and SET_LNB_VOLTAGE (0x8B) -- cmd 0x96 sets which pins are active outputs, while 0x8B and 0x94 set the pin states.


Command 0x97: SET_GPIO_PINS (internal/debug)

Not named in any driver header. This command is not used by either the Linux or Windows driver.

Field Value
Direction OUT (host-to-device)
wValue GPIO pin state bitmap
wIndex 0x0000
wLength 0 (no data phase)
Purpose Direct GPIO pin write for LNB/switch hardware control

Firmware Behavior

v2.06/v2.13:

IOB = (IOB & 0xF1) | (wValueL & 0x0E)

Clears IOB bits [3:1] and sets them to the corresponding bits from wValueL. This gives direct control over the 3 LNB-related GPIO pins on Port B.

Rev.2: Maps individual bits of wValueL to different GPIO pins:

if wValueL.bit1:  P0.6 = 1  else  P0.6 = 0    ; Port A pin 6
if wValueL.bit2:  P0.0 = 1  else  P0.0 = 0    ; Port A pin 0
if wValueL.bit3:  IOB.4 = 1 else  IOB.4 = 0   ; Port B pin 4

Subroutine Addresses

Version Handler GPIO Write
v2.06 0x02C1 0x24BE
v2.13 0x02E5 0x2429
Rev.2 0x02CF 0x1FCF

wValue Bit Mapping

v2.06/v2.13 (Port B bulk write):

wValue Bit GPIO Pin Function
bit 1 IOB.1 LNB regulator control line 1
bit 2 IOB.2 LNB regulator control line 2
bit 3 IOB.3 LNB regulator control line 3

Rev.2 (individual pin mapping):

wValue Bit GPIO Pin Function
bit 1 P0.6 (Port A) LNB control line
bit 2 P0.0 (Port A) LNB control line
bit 3 IOB.4 (Port B) LNB control line

Cross-Version Differences

Major hardware difference: v2.06/v2.13 use a simple Port B mask write, while Rev.2 maps each bit to different pins on two different ports (A and B). This reflects the Rev.2 PCB redesign that moved LNB control circuitry to different FX2 GPIO pins.


Command 0x98: GET_GPIO_STATUS (internal/debug)

Not named in any driver header. This command is not used by either the Linux or Windows driver.

Field Value
Direction IN (device-to-host)
wValue 0x0000
wIndex 0x0000
wLength 1 byte
Returns GPIO input pin state (0 or 1)
Purpose Read LNB-related GPIO input pin state

Firmware Behavior

v2.06/v2.13:

A = IOB & 0x01      ; read Port B bit 0
EP0BUF[0] = A       ; return 0 or 1
EP0BCL = 1

Rev.2:

A = P0               ; read Port A
if P0.5 == 1:
    R7 = 1
else:
    R7 = 0
EP0BUF[0] = R7
EP0BCL = 1

Subroutine Addresses

Version Handler GPIO Read
v2.06 0x02CB 0x24CC
v2.13 0x02EF 0x2437
Rev.2 0x02D9 0x0046

GPIO Pin Read

Version Pin SFR
v2.06 IOB.0 (Port B bit 0) SFR 0xB0, bit 0
v2.13 IOB.0 (Port B bit 0) SFR 0xB0, bit 0
Rev.2 P0.5 (Port A bit 5) SFR 0x80, bit 5

Purpose

This reads a single GPIO input pin, likely a feedback/status signal from the LNB power supply circuitry (overcurrent detect, power-good, or similar). The pin assignment changed with the Rev.2 PCB redesign.

Cross-Version Differences

  • v2.06/v2.13: Reads Port B pin 0 (IOB.0) via mask & 0x01
  • Rev.2: Reads Port A pin 5 (P0.5) via bit test JNB ACC.5
  • Different GPIO pin due to Rev.2 hardware redesign

Summary Table

Cmd Name Dir wValue wLength Purpose
0x8F SET_DN_SWITCH OUT 7-bit switch cmd 0 Legacy Dish Network switch via GPIO bit-bang on P0.4
0x91 I2C_ADDR_ADJUST IN 0=dec, else inc 1 Inc/dec internal IRAM counter (debug)
0x92 GET_FW_VERS IN 0 6 Read firmware version + build date (hardcoded)
0x93 GET_SERIAL_NUMBER IN 0 4 Read 4-byte serial from I2C EEPROM (0x51)
0x94 USE_EXTRA_VOLT OUT 0=off, 1=on 0 Enable +1V LNB boost (13->14V, 18->19V) via XRAM 0xE0B6
0x95 GET_FPGA_VERS IN 0 1 Read EEPROM-stored hardware/platform ID
0x96 SET_LNB_GPIO_MODE OUT 0=default, 1=active 0 Configure LNB GPIO output enables (IOB/OEB)
0x97 SET_GPIO_PINS OUT pin bitmap 0 Direct write to LNB GPIO pins
0x98 GET_GPIO_STATUS IN 0 1 Read LNB feedback GPIO pin (0 or 1)

Driver Usage

Cmd Linux Kernel Windows Driver Firmware
0x8F dishnetwork_send_legacy_command callback Defined in header, not called in source All versions
0x91 Not used Not defined All versions
0x92 gp8psk_get_fw_version() on boot Not defined All versions
0x93 Not called directly (defined in header) Defined in header, not called in source All versions
0x94 enable_high_lnb_voltage callback Defined in header, not called in source All versions
0x95 gp8psk_get_fpga_version() on boot Not defined All versions
0x96 Not used Not defined All versions
0x97 Not used Not defined All versions
0x98 Not used Not defined All versions

Cross-Version Change Summary

Cmd Changed? Details
0x8F No Identical bit-bang algorithm, same GPIO pin P0.4
0x91 Minor IRAM counter address: 0x66 (v2.06) vs 0x18 (v2.13/Rev.2)
0x92 Data only Different hardcoded version bytes per build
0x93 No Same EEPROM read logic, same device 0x51
0x94 Minor Rev.2 returns 1 byte (ack); v2.06/v2.13 return nothing
0x95 Yes v2.06 reads EEPROM offset 0x31, returns 2 bytes; v2.13/Rev.2 read offset 0x00, return 1 byte
0x96 Yes Rev.2 uses different GPIO pins (IOB.4 + Port A) vs v2.06/v2.13 (IOB.3/2/1)
0x97 Yes Rev.2 maps bits to individual pins across two ports; v2.06/v2.13 bulk-writes Port B
0x98 Yes Rev.2 reads P0.5 (Port A); v2.06/v2.13 read IOB.0 (Port B)

FX2 Register Reference

Address Name Purpose
0xE6B8 SETUPDAT[0] bmRequestType
0xE6B9 SETUPDAT[1] bRequest
0xE6BA SETUPDAT[2] wValueL
0xE6BB SETUPDAT[3] wValueH
0xE68A EP0BCH EP0 byte count high
0xE68B EP0BCL EP0 byte count low (write triggers transfer)
0xE740 EP0BUF EP0 data buffer start
0xE0B6 (custom) LNB voltage control register
SFR 0x80 P0 / IOA Port A (Port 0) data register
SFR 0xB0 P3 / IOB Port B data register
SFR 0xB2 OEA Port A output enable
SFR 0xB5 OEB Port B output enable