Vendor Commands
All vendor commands use USB control transfers with USB_TYPE_VENDOR (bmRequestType bit 6 set). The vendor command dispatcher at CODE:0056 validates bRequest in the range 0x80—0x9D (30 entries for v2.06/v2.13) or 0x80—0x9A (27 entries for Rev.2) and dispatches via an indexed jump table at CODE:0076.
Stock Command Table (0x80—0x9D)
Section titled “Stock Command Table (0x80—0x9D)”| Cmd | Name | Dir | wValue | wIndex | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|---|---|---|---|---|---|---|---|---|---|
| 0x80 | GET_8PSK_CONFIG | IN | 0 | 0 | 1 | Read configuration status byte | OK | OK | OK |
| 0x81 | SET_8PSK_CONFIG | OUT | varies | 0 | 0 | Set config (reserved) | STALL | STALL | STALL |
| 0x82 | (reserved) | — | — | — | — | Reserved | STALL | STALL | STALL |
| 0x83 | I2C_WRITE | OUT | dev_addr | reg_addr | N | Write to I2C device | OK | OK | OK |
| 0x84 | I2C_READ | IN | dev_addr | reg_addr | N | Read from I2C device | OK | OK | OK |
| 0x85 | ARM_TRANSFER | OUT | 0/1 | 0 | 0 | Start (1) / stop (0) MPEG-2 stream | OK | OK | OK |
| 0x86 | TUNE_8PSK | OUT | 0 | 0 | 10 | Set tuning parameters | OK | OK | OK |
| 0x87 | GET_SIGNAL_STRENGTH | IN | 0 | 0 | 6 | Read SNR and diagnostics | OK | OK | Changed |
| 0x88 | LOAD_BCM4500 | OUT | 1 | 0 | 0 | Initiate BCM4500 FW download | STALL | STALL | STALL |
| 0x89 | BOOT_8PSK | IN | 0/1 | 0 | 1 | Power on (1) / off (0) demodulator | OK | OK | OK |
| 0x8A | START_INTERSIL | IN | 0/1 | 0 | 1 | Enable (1) / disable (0) LNB supply | OK | OK | OK |
| 0x8B | SET_LNB_VOLTAGE | OUT | 0/1 | 0 | 0 | 13V (0) or 18V (1) | OK | OK | OK |
| 0x8C | SET_22KHZ_TONE | OUT | 0/1 | 0 | 0 | Tone off (0) or on (1) | OK | OK | OK |
| 0x8D | SEND_DISEQC_COMMAND | OUT | msg[0] | 0 | len | DiSEqC message or tone burst | OK | OK | OK |
| 0x8E | SET_DVB_MODE | OUT | 1 | 0 | 0 | Enable DVB-S mode | STALL | STALL | STALL |
| 0x8F | SET_DN_SWITCH | OUT | cmd7bit | 0 | 0 | Legacy Dish Network switch protocol | OK | OK | OK |
| 0x90 | GET_SIGNAL_LOCK | IN | 0 | 0 | 1 | Read signal lock status | OK | OK | OK |
| 0x92 | GET_FW_VERS | IN | 0 | 0 | 6 | Read firmware version + build date | OK | OK | OK |
| 0x93 | GET_SERIAL_NUMBER | IN | 0 | 0 | 4 | Read 4-byte serial from EEPROM | OK | OK | OK |
| 0x94 | USE_EXTRA_VOLT | OUT | 0/1 | 0 | 0 | Enable +1V LNB boost (14V/19V) | OK | OK | OK |
| 0x95 | GET_FPGA_VERS | IN | 0 | 0 | 1 | Read EEPROM hardware/platform ID | OK | OK | OK |
Detailed Parameter Formats
Section titled “Detailed Parameter Formats”0x87 GET_SIGNAL_STRENGTH: Returns 6 bytes. Bytes 0—1 contain a 16-bit SNR value (little-endian, dBu x 256 units). Bytes 2—5 are reserved/diagnostic BCM4500 registers. Version differences: v2.06 polls 3 registers (0xA2, 0xA8, 0xA4) up to 6 times; v2.13 consolidates to 1 register with a simplified poll.
0x8D SEND_DISEQC_COMMAND: When wLength > 0, the payload is a standard DiSEqC message (3—6 bytes) with wValue set to msg[0] (framing byte, typically 0xE0 or 0xE1). When wLength == 0 and wValue == 0, tone burst A is sent. When wLength == 0 and wValue != 0, tone burst B is sent.
0x8F SET_DN_SWITCH: wValue carries a 7-bit Dish Network switch command (LSB-first), bit-banged on GPIO P0.4 with specific timing. The 8th bit (0x80) of the original switch command selects LNB voltage and is sent separately via SET_LNB_VOLTAGE.
0x92 GET_FW_VERS: Returns 6 bytes of hardcoded constants:
Byte 0: version minor_minor (e.g., 0x04)Byte 1: version minor (e.g., 0x06)Byte 2: version major (e.g., 0x02)Byte 3: build day (e.g., 0x0D = 13)Byte 4: build month (e.g., 0x07 = July)Byte 5: build year - 2000 (e.g., 0x07 = 2007)
Full version = byte[2] << 16 | byte[1] << 8 | byte[0]Build date = (2000 + byte[5]) / byte[4] / byte[3]0x93 GET_SERIAL_NUMBER: Returns 4 bytes read from I2C EEPROM at device address 0x51 (7-bit), extracted at 8-bit intervals using a shift/rotate routine.
0x94 USE_EXTRA_VOLT: wValue=1 writes 0x6A to XRAM 0xE0B6; wValue=0 writes 0x62. The difference is bit 3 (0x08), which controls the voltage boost on the LNB power regulator.
0x95 GET_FPGA_VERS: Reads from I2C EEPROM at 0x51. Despite the name, there is no FPGA on the SkyWalker-1 — this returns a hardware platform ID. v2.06 reads EEPROM offset 0x31 (2 bytes); v2.13/Rev.2 read offset 0x00 (1 byte).
Debug Commands (0x91, 0x96—0x98)
Section titled “Debug Commands (0x91, 0x96—0x98)”These commands are not used by any driver (Linux or Windows). They appear to be manufacturing/debug interfaces.
| Cmd | Name | Dir | wValue | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|---|---|---|---|---|---|---|---|---|
| 0x91 | I2C_ADDR_ADJUST | IN | 0=dec, 1=inc | 1 | Inc/dec internal IRAM counter | OK | OK | OK |
| 0x96 | SET_LNB_GPIO_MODE | OUT | 0/1 | 0 | Configure LNB GPIO output enables | OK | OK | OK |
| 0x97 | SET_GPIO_PINS | OUT | bitmap | 0 | Direct write to LNB GPIO pins | OK | OK | OK |
| 0x98 | GET_GPIO_STATUS | IN | 0 | 1 | Read LNB feedback GPIO pin | OK | OK | OK |
0x91 I2C_ADDR_ADJUST
Section titled “0x91 I2C_ADDR_ADJUST”Increments (wValue != 0) or decrements (wValue == 0) an internal IRAM counter and returns its current value (1 byte). The counter lives at IRAM 0x66 (v2.06) or IRAM 0x18 (v2.13/Rev.2). Likely used for I2C address or tuner register index adjustment during development.
0x96 SET_LNB_GPIO_MODE
Section titled “0x96 SET_LNB_GPIO_MODE”Configures GPIO output enable registers for the LNB voltage regulator hardware:
| Mode | v2.06/v2.13 | Rev.2 |
|---|---|---|
| Default (wValue=0) | OEB=0xF0 | OEB=0xE7, OEA=0x9E |
| Active (wValue=1) | IOB=(IOB & 0xF7) OR 0x06; OEB=0xFE | IOB.4 clear; P0.6, P0.0 set; OEA OR= 0x41 |
0x97 SET_GPIO_PINS
Section titled “0x97 SET_GPIO_PINS”Direct GPIO pin write for LNB control:
| wValue Bit | v2.06/v2.13 Target | Rev.2 Target |
|---|---|---|
| bit 1 | IOB.1 (Port B) | P0.6 (Port A) |
| bit 2 | IOB.2 (Port B) | P0.0 (Port A) |
| bit 3 | IOB.3 (Port B) | IOB.4 (Port B) |
0x98 GET_GPIO_STATUS
Section titled “0x98 GET_GPIO_STATUS”Returns 1 byte (0 or 1) from a single GPIO input pin — likely an LNB overcurrent or power-good feedback signal:
| Version | Pin Read |
|---|---|
| v2.06/v2.13 | IOB.0 (Port B bit 0) |
| Rev.2 | P0.5 (Port A bit 5) |
Extended Commands (0x99—0x9D)
Section titled “Extended Commands (0x99—0x9D)”| Cmd | Name | Dir | wValue | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|---|---|---|---|---|---|---|---|---|
| 0x99 | GET_DEMOD_STATUS | IN | 0 | 1 | Read BCM4500 register 0xF9 | STALL | Proto | OK |
| 0x9A | INIT_DEMOD | OUT | 0 | 0 | Trigger demod re-init (3 attempts) | STALL | Proto | OK |
| 0x9B | (reserved) | — | — | — | Reserved | STALL | N/A | STALL |
| 0x9C | DELAY_COMMAND | OUT | delay | 0 | Host-controlled tuning delay + poll | STALL | N/A | OK |
| 0x9D | CW3K_INIT / SET_MODE_FLAG | OUT | 0/1 | 0 | CW3K init or conditional demod reset | OK | N/A | Changed |
Driver Usage Notes
Section titled “Driver Usage Notes”- The Linux driver only sends LOAD_BCM4500 (0x88) for Rev.1 Warm (PID 0x0201). On SkyWalker-1,
bm8pskFW_Loadedis already set and 0x88 routes to STALL. - The Linux driver only sends CW3K_INIT (0x9D) for SkyWalker CW3K (PID 0x0206).
- Rev.2 supports only commands 0x80—0x9A (27 entries). Commands 0x9B—0x9D are out of range and produce undefined behavior.
Custom Firmware Commands (0xB0—0xB9)
Section titled “Custom Firmware Commands (0xB0—0xB9)”Commands added in custom firmware v3.01.0—v3.02.0 for development, diagnostics, and signal monitoring:
| Cmd | Name | Dir | wValue | wIndex | wLength | Purpose |
|---|---|---|---|---|---|---|
| 0xB0 | SPECTRUM_SWEEP | OUT | 0 | 0 | 10 | Step through freq range, read SNR at each step |
| 0xB1 | RAW_DEMOD_READ | IN | reg | 0 | 1 | Read BCM4500 indirect register |
| 0xB2 | RAW_DEMOD_WRITE | OUT | reg | data | 0 | Write BCM4500 indirect register |
| 0xB3 | BLIND_SCAN | OUT | 0 | 0 | 16 | Try symbol rates at given freq, report lock |
| 0xB4 | I2C_BUS_SCAN | IN | 0 | 0 | 16 | Probe all 7-bit addresses, return 16-byte bitmap |
| 0xB5 | I2C_RAW_READ | IN | addr7 | reg | N | Combined write-read from any I2C device |
| 0xB6 | I2C_DIAG | IN | page | 0 | 8 | Step-by-step indirect register diagnostic |
Parameter Formats
Section titled “Parameter Formats”0xB0 SPECTRUM_SWEEP: 10-byte EP0 payload: [start_freq(u32 LE kHz), stop_freq(u32 LE kHz), step_khz(u16 LE)]. Programs BCM4500 at each frequency step, reads SNR, packs u16 LE results into EP2 bulk FIFO.
0xB3 BLIND_SCAN: 16-byte EP0 payload: [freq_khz(u32 LE), sr_min(u32 LE sps), sr_max(u32 LE sps), sr_step(u32 LE sps)]. Returns 8 bytes on lock [freq_khz(4) + sr_locked(4)] or 1 byte 0x00 if no lock found.
0xB4 I2C_BUS_SCAN: Returns a 16-byte bitmap (128 bits for addresses 0x00—0x77). Each bit set = ACK received at that 7-bit address.
Signal Monitoring Commands (v3.02.0) v3.02
Section titled “Signal Monitoring Commands (v3.02.0) ”| Cmd | Name | Dir | wValue | wIndex | wLength | Purpose |
|---|---|---|---|---|---|---|
| 0xB7 | SIGNAL_MONITOR | IN | 0 | 0 | 8 | Fast combined signal read: SNR(2) + AGC1(2) + AGC2(2) + lock(1) + status(1) |
| 0xB8 | TUNE_MONITOR | OUT+IN | dwell_ms | 0 | 10 | Tune + dwell + signal read. OUT=tune payload, IN=result |
| 0xB9 | MULTI_REG_READ | IN | start_reg | count | count | Batch read of contiguous BCM4500 indirect registers (1—64) |
0xB7 SIGNAL_MONITOR: Returns 8 bytes in one transfer: [snr_lo, snr_hi, agc1_lo, agc1_hi, agc2_lo, agc2_hi, lock_0xA4, status_0xA2]. SNR is from indirect regs 0x00—0x01 (dBu × 256). AGC values from regs 0x02—0x05. Lock/status from direct registers. Enables ~50 Hz polling.
0xB8 TUNE_MONITOR: Two-phase protocol sharing bRequest=0xB8. Phase 1 (OUT, bmRequestType=0x40): 10-byte EP0 payload in TUNE_8PSK format, wValue=dwell_ms (1—255). Firmware tunes, waits dwell_ms, reads signal into static buffer. Phase 2 (IN, bmRequestType=0xC0): returns 10-byte result [snr(6), lock(1), status(1), dwell_echo(2)]. The OUT phase blocks for the full dwell time.
0xB9 MULTI_REG_READ: wValue = start register, wIndex = count (1—64). Returns count bytes, one per register, in a single USB transfer. Each register still requires an individual I2C indirect read internally, but saves 63 USB round-trips for register exploration.
Vendor Command Dispatch Mechanism
Section titled “Vendor Command Dispatch Mechanism”The dispatch logic at CODE:0056 (identical address across all stock versions):
1. Check bmRequestType bit 6 -> vendor request?2. Read bRequest from SETUPDAT[1]3. Subtract 0x80 (command base offset)4. Compare against maximum: < 0x1E (v2.06/v2.13) or < 0x1B (Rev.2)5. If in range: double the index (2 bytes per AJMP) -> JMP @A+DPTR6. If out of range: route to STALL handlerThe jump table at CODE:0076 contains 2-byte AJMP instruction targets, one per command from 0x80 upward.