pvrusb2 driver manual firmware extraction

$Id: firmware.html 2425 2009-11-14 17:01:14Z isely $

Mike Isely <isely at pobox dot com>

You can find the main driver page on the web at http://www.isely.net/pvrusb2/pvrusb2.html.

This page provides additional information related to manually extracting the firmware needed for the PVR USB2 hardware. (There is an easier way to do this; please try this procedure first before wading through this page.)


Contents

Overview
cx23416 & cx25840 firmware capture
FX2 firmware capture
Locating the Firmware

Overview

Hardware driven by the pvrusb2 driver has several parts within it that require firmware images to be loaded first in order to operate correctly. That firmware is not a part of this driver; you must obtain it from elsewhere (e.g. your Windows driver CD, the device maker's web site, or perhaps a 3rd party). In addition, the exact firmware files you will need will depend on which device you have. Whether you are using the standalone pvrusb2 driver snapshot or the in-V4L version of the pvrusb2 driver, you will need to obtain and install the appropriate firmware images before your device will function correctly.

The easiest means for obtaining or extracting the firmware is NOT described here. It is instead documented as part of the normal driver setup. You can find that information in the Firmware retrieval and installation section within setup.html. Try there first, and if that failed to work, then read on.

There is the occasional situation where the easy method doesn't work. It is possible that fwextract.pl might not recognize your driver package (you did uncompress it first, right?) no matter what you throw at it; you'll see messages of the form "failed to locate data for writing filename" (where filename is the firmware file it tried to generate). Or you might find that only some - not all - of the firmware files were found. This can happen if the device vendor releases new drivers and fwextract.pl hasn't been updated yet. If this is indeed the case, then things are somewhat more difficult - we need to manually identify the firmware data and teach the script where to find it when it encounters the new driver package.

Basically what has to be done if this happens is something like this:

  1. Possibly find some alternate means to get the firmware data.
  2. Run "fwextract.pl --search".

There are three approaches to the first step. One approach is that someone good at reverse-engineering starts hacking away with a hex editor to find the embedded data. Yuck. A second approach is to capture the firmware from the hardware itself - which we can do. There are typically two pieces of data to capture: the cx23416 (mpeg encoder) firmware and the FX2 (device microcontroller) firmware. If you have 24xxx, Gotview, or HVR-1950 hardware, then you also need to capture the cx25840 (video & audio digitizer) firmware as well. Note: The Gotview and OnAir devices store the FX2's program in a local ROM so there's no need to worry about FX2 firmware in those cases. But there's a third approach to this step: you might be able to skip it completely (see further)...

The second step runs a process to scan the original Windows driver files and find where the firmware (previously fetched here in step 1 or previously known by fwextract.pl) is hiding. Once found, fwextract.pl will write a few simple text records to the terminal needed by the extractor for locating the firmware in the future. You need only append those lines to the fwextract.pl program itself for the new information to be used. But also send that extra text to me and I'll update the master copy of fwextract.pl so that other users can benefit from your hacking effort.

I mentioned possibly skipping that first step. You might be able to get away with that. How? The fwextract.pl program, marked with Subversion ID 2422 or later, now has the ability to include everything it knows about previously found firmware while executing that search. If the driver you are searching happens to only include firmware we know about already, then that first painful step of manually retrieving the firmware can be skipped. This is handy because frequently a new driver might be released but the binary firmware data hasn't changed. In those cases that first step might not actually be needed. You can try to just run the second step and if it locates all the required images (see further down for the list) then you've avoided nearly all of the work! Note however that I'd still like to be sent any records emitted by that second step - even though the search was quick, it still had to be done and if I can integrate the results back into fwextract.pl then you've saved others from having to understand any of this and sitting through another search process :-)

Note that if you are using an fwextract.pl version older than Subversion ID 2422, not only do you not have that nice implicit search feature described above, but the emitted records resulting from that search will instead be a more complex Perl data structure. In that case you will have to edit the data back inside the script. It's much easier to use the newer fwextract.pl which implements this simpler record format. Odds are that's what you are using, but in case you get something strange instead look at the version string printed when it runs and see if you're running the old version.

cx23416 & cx25840 firmware capture

To manually capture the cx23416 and cx25840 firmware images, you need to use the USB sniffer to grab it "in flight" from within Windows and then use several tools included with the standalone driver snapshot to extract the firmware data from the stream.

The USB sniffer is a handy free utility that can be found at http://benoit.papillault.free.fr/usbsnoop/. Make sure you grab the latest version of the sniffer - the download list on the site shows version oldest to newest, so be sure to scroll to the bottom of the list. The sniffer version I've used is 1.8.

The additional tools you will need are included with the standalone driver snapshot. Specifically, you will need usbreplay.pl to distill the output of the USB sniffer down to a simpler form, and you will need the decompiler (decode_log with the "--firmware" option) to extract the firmware data from the stream. Note that the decompiler is C++; if you haven't yet compiled it then just run make in the utils directory to build it.

Additional information about all of this can be found in the Sniffing and decompiling USB traffic section of of the utils.html page.

The process is roughly the same regardless of the type of hardware you have - you'll get one file out of this if you are using 29xxx hardware and two files if you are using 24xxx or Gotview hardware. Here's the exact procedure:

  1. Boot up Windows and start the USB sniffer. Plug in the pvrusb2 device. You don't need to run anything but just wait for the sniffer to collect the log data from when the driver initializes the device.
  2. Copy the sniffer's log data to some place where you can get at it from Linux.
  3. Boot Linux.
  4. Run this sequence (substitute "usbsnoop.log" with the file you got from the sniffer):
  5. usbreplayprep.pl < usbsnoop.log | decode_log --firmware firmware_file > /dev/null

The result of that last step will be either 1 or 2 files. If you are using 29xxx hardware you should see one file named "firmware_file". Otherwise you should see two files, named "firmware_file-1" and "firmware_file-2". You need to rename these files. For 29xxx hardware with a single file, just do this:

mv firmware_file v4l-cx2341x-enc.fw

For 24xxx or Gotview hardware, you first need to figure out which file is which and then rename them accordingly. You must not get this backwards! One file will be approximately 256KB (or slightly larger) in size - that will be the cx23416 image and you should rename that to "v4l-cx2341x-enc.fw". The other file will be roughly 13KB in size (this might vary); rename that file to "v4l-cx25840.fw".


FX2 firmware capture

If you are using a Gotview or OnAir device, the FX2 program is held in the device in ROM, so there's no FX2 firmware to extract and you can safely skip this entire part of the procedure.

Important note: If you are using the in-V4L or in-kernel versions of the pvrusb2 driver, be sure you have built it with the debug interface option (CONFIG_VIDEO_PVRUSB2_DEBUGIFC) enabled. Doing this enables a feature that you need in order to capture the FX2 firmware. Frequently distro-supplied precompiled kernels will not have this option set! For the standalone pvrusb2 driver, this is enabled by default. If you are using a distro-supplied kernel and it appears that the debug interface is not enabled, it is probably easier to just grab and build the standalone driver rather than trying to recompile a piece of the distro's kernel package...

Capturing of the FX2 firmware is entirely different. The USB sniffer doesn't see this traffic right now so we have to take a different strategy. I've added a feature to the pvrusb2 driver that makes possible the direct retrieval of the firmware data from the device. Here's the procedure:

  1. Boot up Windows, power cycle the device, and then plug in the pvrusb2 device.
  2. Reboot to Linux LEAVING THE PVRUSB2 DEVICE POWERED UP.
  3. Execute this sequence (substitute your device's serial number for "XXXXXXX" and change "/dev/video0" to match the /dev name corresponding to your device):
    echo "cpufw fetch" >/sys/class/pvrusb2/sn-XXXXXXX/debugcmd
    cat /dev/video0 >/tmp/fx2.fw
    echo "cpufw done" >/sys/class/pvrusb2/sn-XXXXXXX/debugcmd
  4. Rename the firmware file to correspond to your hardware type. For 29xxx hardware, rename fx2.fw to v4l-pvrusb2-29xxx-01.fw. For 24xxx hardware, rename fx2.fw to v4l-pvrusb2-24xxx-01.fw. For HVR-1950 hardware, rename fx2.fw to v4l-pvrusb2-73xxx-01.fw. This differentiation of firmware name is extremely important because the FX2 firmware is actually different and incompatible among all device versions.

Very important exception to the above procedure: If you are doing this on an HVR-1950 device, then it is likely that the firmware image will be 16KB (16384) instead of 8KB (8192). The above procedure only grabs the first 8KB and this will ultimately result in corrupted firmware (it won't be subtle when you later test it). To deal with this, modify the first echo command to be this instead:

echo "cpufw fetch ram16k" >/sys/class/pvrusb2/sn-XXXXXXX/debugcmd

That tells the pvrusb2 driver to grab 16KB instead of 8KB. (Yes I can make this work smarter but that still needs more work.)

It is imperative that you do not power cycle the device when switching from Windows to Linux. This allows the FX2 firmware to be retained in the device's memory, and will cause the pvrusb2 Linux driver to not attempt to reload the firmware. Thus when you run the command sequence to pull the firmware back, you'll get what had previously been loaded by Windows.

Your device will reset itself after the "cpufw done" debug command is sent to the driver. The file /tmp/v4l-pvrusb2-29xxx-01.fw for 29xxx hardware (or /tmp/v4l-pvrusb2-24xxx-01.fw for 24xxx hardware) is an image of the FX2's program memory. Note that this isn't the exact bit-for-bit copy of the firmware file you need; apparently the FX2 program modifies itself slightly. However it's close enough that the fwextract.pl program's --search feature can still locate the pristine firmware data using a fuzzy matching algorithm (which it will fall back to if an exact search doesn't find it).


Locating the Firmware

After you've gotten the firmware images retrieved and named correctly, put copies of all the files in the current directory (if you haven't already done so). The exact set of files to have copied will depend on your hardware type; just to review, by this point you should have copied across the following names:

For 29xxx hardware:

v4l-cx2341x-enc.fw
v4l-pvrusb2-29xxx-01.fw

For 24xxx hardware:

v4l-cx2341x-enc.fw
v4l-pvrusb2-24xxx-01.fw
v4l-cx25840.fw

For Gotview hardware:

v4l-cx2341x-enc.fw
v4l-cx25840.fw

For OnAir hardware:

v4l-cx2341x-enc.fw

For HVR-1950 hardware:

v4l-cx2341x-enc.fw
v4l-pvrusb2-73xxx-01.fw
v4l-cx25840.fw

Now unpack the vendor's Windows driver package again into an empty "win_driver" subdirectory, then run fwextract.pl --search. (If you installed from a cdrom, you can alternatively mount the cdrom under Linux and use the --driverDir=<path> option to point at the mount point instead of the default win_driver subdirectory.) After a few moments or so (longer if it has to drop into "fuzzy search mode") it will print the magic few records of text data that can then be appended to fwextract.pl so it will now automatically understand how to extract this firmware data in the future. Send those records to me (along with a description of the driver package) and I'll ensure that the next release of fwextract.pl includes it.

You should in theory be able to just use the manually extracted firmware files. However the FX2 firmware image (one of v4l-pvrusb2-29xxx-01.fw, v4l-pvrusb2-24xxx-01.fw, or v4l-pvrusb2-73xxx-01.fw) may not be exactly identical to what is really loaded, so you may really want to go back and get the real firmware out of the driver directory anyway. Do the following:

  1. Edit your copy of fwextract.pl and append that previously printed magic chunk of record data onto it - it should be obviously by inspection exactly what will be needed. Or you can just echo >>fwextract.pl and mouse-paste the new records followed by an EOF (Ctrl-D) to end the operation.
  2. Now go back and just run a normal extraction operation (e.g. that which is documented in the Firmware extraction and installation section within setup.html.

Don't forget to send me that magic chunk of data so that I can update the master copy of fwextract.pl. Please also include a 1 line description that indicates some kind of uniquely identifiable attribute of the driver package from where you extracted the firmware. You can find my e-mail address at the top of pvrusb2.html.