Skip to content

Rev.2 Firmware Analysis

The Rev.2 v2.10.4 firmware targets the Rev.2 hardware variant (PID 0x0202) and contains 107 functions — the most of any firmware version. Despite this, it produces the smallest binary (8,843 bytes) due to aggressive function decomposition into small helper routines.

Rev.2 sits architecturally between v2.06 and v2.13:

Aspectv2.06Rev.2 v2.10v2.13
INT0 behaviorUSB re-enumerationUSB re-enumerationDemod polling
Descriptor base0x12000x0E000x0E00
Stack pointer0x720x4F0x50
Vendor command range0x800x9D (30)0x800x9A (27)0x800x9D (30)
Demod probe at bootNoNoYes
Retry loopsNoNoYes
Function count6110782-88
Binary size9,472 bytes8,843 bytes9,322 bytes

The high function count is driven by three factors:

  1. Granular decomposition: Rev.2 breaks large operations into many small helper functions (10-30 bytes each), where v2.06 inlines the same logic and v2.13 recombines it differently.

  2. Massive configuration dispatcher: FUN_CODE_0800 is 874 bytes and contains an embedded copy of the main loop, causing Ghidra to count additional entry points as separate functions.

  3. Extra I2C/demodulator helper chains: GPIO control primitives, hardware-polling wait loops, and I2C bus management exist as individual callable units rather than being inlined.

The 107 functions are organized into logical groups:

Vector Table and ISR Region (0x0000—0x0055)

Section titled “Vector Table and ISR Region (0x0000—0x0055)”
AddressNameSizeRole
0x0000RESET_vector3Jump to main at 0x155F
0x0003INT0_ISR12INT0 handler — USB re-enumeration
0x000FINT0_ISR_bit_clear36CPUCS pulse, IRQ clear, delay
0x0033INT2_USB_GPIF_vector3Clears CCON.4 (PCA timer)
0x0036i2c_exchange_byte5I2C byte exchange primitive
0x003BI2C_ISR8I2C interrupt handler
0x0043INT4_FX2_vector8Sets _0_1 flag, clears EXIF.4
0x004BINT5_FX2_vector3Empty (RETI)
0x0053INT6_FX2_vector3Sets _0_1 flag, clears EXIF.4
AddressNameSizeRole
0x0056vendor_cmd_dispatch342Range check 0x800x9A, jump table at 0x0076
0x01ACGET_8PSK_CONFIG handler361Reads config byte, calls LNB probe
0x0315vendor_cmd_stall2Stall handler (empty RET)
0x0319Standard USB request handler869Switch for bRequest 0x000x0B

Configuration and Tuning (0x0800—0x09A8)

Section titled “Configuration and Tuning (0x0800—0x09A8)”
AddressNameSizeRole
0x0800Config/tuning dispatcher874128-entry switch on demod type, embedded main loop
0x09A9Main init + main loop699Hardware init, infinite poll loop
AddressNameSizeRole
0x0C64BCM4500 firmware loader280I2C block transfer with address tracking
0x0D7CGPIF/slave FIFO config128Enable/disable streaming mode
0x0F00I2C multi-byte read256Parameter setup for bus transfer

DiSEqC Implementation (0x07D1, 0x1D5E—0x1E3D)

Section titled “DiSEqC Implementation (0x07D1, 0x1D5E—0x1E3D)”
AddressNameSizeRole
0x07D1DiSEqC byte transmit458 data bits + odd parity via P0.4
0x1D5EDiSEqC message sender59Iterates bytes, calls bit-bang per byte
0x1E3DDiSEqC byte wrapper54Sets P0.2, adds inter-byte delay
0x213CDiSEqC bit symbol22Carrier on/off via P0.3, data via P0.4
0x20E222 kHz tone burst23P0.3 ON, 25 ticks, P0.3 OFF
0x225FTimer2 tick wait6TF2 poll and clear (500 us tick)
AddressNameSizeRole
0x1F5CLNB voltage I2C select41Probes I2C device 0x60 or address from 0xE0B6
0x1FCFGPIO pin controller46Sets P0.6, P0.0, P3.4 based on parameter bits
0x2038GPIO clock strobe51Calls pin controller 3 times (setup, clock, cleanup)
0x21B1LNB voltage select17Sets/clears P0.4, updates config bit 5
0x21C222 kHz tone enable17Sets/clears P0.3, updates config bit 4
0x21D3DiSEqC port direction17Sets/clears P3.6, updates config bit 3

Rev.2 decomposes I2C operations into particularly fine-grained functions:

AddressNameSizeRole
0x19F4I2C bus controller92Manages SDA/SCL via XRAM 0xE678
0x1A50I2C address select + start83START condition generation
0x1AA3I2C stop + cleanup82STOP condition and bus release
0x1AF5I2C address write helper9Writes device address byte
0x1B01I2C byte-level transfer67Single byte send/receive
0x1B44I2C ACK/NAK handling76Acknowledge detection
0x1B90I2C bus reset/recovery74Error recovery sequence
0x1F06I2C completion wait43Polls XRAM 0xE678 bit 0 with 16-bit timeout
0x1F85I2C completion wait (2-flag)37Polls bits 0 and 2
0x2000I2C busy wait30Polls XRAM 0xE678 bit 6 with timeout

A unique function that provides parameterized GPIO control through a bit-field interface:

GPIO pin controller (decompiled)
void gpio_pin_controller(BYTE param) {
if (param & 0x02) P0 |= 0x01; // P0.0
else P0 &= ~0x01;
if (param & 0x04) P0 |= 0x40; // P0.6
else P0 &= ~0x40;
if (param & 0x08) P3 |= 0x10; // P3.4
else P3 &= ~0x10;
}

This function is called via FUN_CODE_2038 (GPIO clock strobe) which invokes it three times per cycle — setup, clock edge, and cleanup — suggesting it controls a clocked peripheral interface.

Descriptor Version Checker (FUN_CODE_1f31)

Section titled “Descriptor Version Checker (FUN_CODE_1f31)”

Walks a USB descriptor chain checking whether descriptor_byte + 1 == 0x03, enabling hardware-revision-aware code paths. This mechanism appears in a simplified form in v2.13 as the _1_3 flag check.

Commands 0x99 and 0x9A exist in Rev.2 as partial prototype implementations, before becoming fully functional in v2.13:

CommandRev.2 Behaviorv2.13 Behavior
0x99Prototype — limited status readFull GET_DEMOD_STATUS (reads BCM4500 reg 0xF9)
0x9APrototype — basic init callFull INIT_DEMOD (3-attempt re-init with flag check)

Key Rev.2 functions and their counterparts in other versions:

Rev.2 FunctionRolev2.06v2.13
0x155F mainRESET entry, IRAM clear0x188D0x170D
0x09A9 main initInit + main loop0x09A70x0800
0x10D9 USB setupDescriptor/peripheral init0x13C30x11AB
0x0056 vendor dispatchVendor command dispatcher0x00560x0056
0x0C64 BCM4500 loaderFirmware block transfer0x0DDD0x0CA4
0x0D7C GPIF/FIFOStreaming management0x19190x1800
0x1BDA delayClock-compensated delay0x1DFB0x14B9

The Rev.2 board has a different GPIO assignment from the standard SkyWalker-1:

PinRev.2 v2.10v2.06 / v2.13
P0.0LNB control (cmd 0x97)DiSEqC data (v2.13) / unused (v2.06)
P0.4LNB voltage + DiSEqC dataLNB voltage only
P0.5GPIO status input (cmd 0x98)BCM4500 RESET
P0.6GPIO control (cmd 0x97)Unused
P0.7Streaming indicatorDiSEqC data (v2.06) / streaming (v2.13)

The most significant difference is that Rev.2 multiplexes DiSEqC data onto the LNB voltage pin (P0.4), and the BCM4500 RESET function on P0.5 is replaced by a GPIO status input.

The Rev.2 main loop follows the same pattern as other versions but with the event handling delegated to FUN_CODE_201e:

Main loop poll (simplified)
void main_loop(void) {
// Process init table from CODE:0B48
// Call USB/peripheral setup
// Enable interrupts
while (1) {
if (sudav_flag) {
handle_setupdata();
sudav_flag = 0;
}
FUN_CODE_201e(); // Delegated I2C config read/write
if (gpif_flag) {
handle_gpif_event();
gpif_flag = 0;
} else {
PCON |= 0x01; // CPU idle
}
}
}