NSLU2-Linux
view · edit · print · history

Installing a Hauppauge WinTV PVR USB2

(Simplified instructions for OpenSlug 2.7/3.10 are at the end.)

Unfortunately this package for whatever reason got dropped from SlugOS 3.10. It is in the unstable feed. This version does not require you to copy the hotplug functions.

There are new hardware versions of the WinTV PVR USB2, the driver is still in development! Read more here http://www.isely.net/pvrusb2.html#Caveat. The latest version in the head supports this new hardware version, but it is not as well tested as the old hardware.

Note: this howto is for the 2.6.12 kernel (e.g. OpenSlug 2.5). However, there is a flaw in the x1205 RTC driver in that release which causes a crash when you have multiple I²C busses present (1 in the NSLU2 for the RTC and 1 in the WinTV PVR USB2). When using the WinTV PVR USB2 with a 2.6.12 kernel, you will have to disable or remove the x1205 RTC driver. This will disable the ability for the NSLU2 to keep track of the time whilst off however.

It is also possible to get the WinTV PVR USB2 working under 2.6.14. However, this requires some code changes and is still quite messy. If you are interested, drop me (eFfeM) a note...

Introduction

This howto describes how to install the Hauppauge WinTV PVR USB2 on your NSLU2. This howto and linked drivers are only for this specific model. Other WinTV PVR devices exist which are incompatible because they are PCI cards. A special note is that it must be the USB2 version of the PVR, there is an older model which is USB1 only which is also not compatible.

This howto has been tested with OpenSlug 2.5. It should also work on the OpenSlug head. You will have to work out the necessary steps for Unslung if you wish to use it under that distribution.

Note: This howto assumes you have experience of Linux, that you have a cross development environment and that you know how to build and flash a kernel.

Building the drivers

There are two different methods to build the drivers.

Method 1: Use the pvrusb2-mci package

This uses the package built by dyoung. It is available as the pvrusb2-mci package on the development head. You might be able to use this with OpenSlug 2.5 as well (I haven't tested this). After building the head copy pvrusb2-mci.ipk to the slug and do a ipkg install pvrusb2-mci

Method 2: Adding it into OpenSlug 2.5

Alternatively one can add the driver into OpenSlug 2.5. This is a little bit more tricky but has the benefit that the kernel itself is more stable (you won't be bitten by unexpected changes elsewhere in the head).

First you'll need to obtain the driver software. This can be found at pvrusb2 Linux driver page. It is a good idea to read this page and the FAQ to learn a little bit about what is going on. I used driver snapshot pvrusb2-mci-20050921.tar.bz2.

The steps to get to the software (all modules) is as follows:

  • Build the stock kernel (source setup-env;bb openslug-kernel
  • cd tmp/work/openslug-kernel-2.6.12.2-r6/linux-2.6.12.2/drivers
  • Unzip and untar your snapshot. If you used the snapshot above that will give you a directory pvrusb2-mci-20050921/driver. Rename this directory to pvrusb2. Move the files from the driver subdirectory to the pvrusb2 directory.
  • In the Makefile in the drivers directory add a line:
    obj-y += pvrusb2/
    also change the line
    obj-y += firmware/
    into
    obj-m += firmware/
  • Change directory to ../../../../stamps and remove

openslug-kernel-2.6.12.2-r6.do_compile; do not do a bb -cclean as this will remove the pvrusb2 directory and your edit in the makefile

  • Build the kernel again.
  • In tmp/work/openslug-kernel-2.6.12.2-r6/linux-2.6.12.2/drivers/pvrusb2
    you'll now find msp3400.ko pvrusb2.ko saa7115.ko tuner.ko tveeprom.ko
    Copy these to the slug. I've stuffed them into /lib/modules/2.6.12.2/pvrusb2 (you'll need to make this directory first)
  • In tmp/work/openslug-kernel-2.6.12.2-r6/linux-2.6.12.2/drivers/base you'll find firmware_class.ko. Also copy this to the slug (in /lib/modules/2.6.12.2/pvrusb2). Apparently pvrusb2.ko requires this as a module. If you find a way to do without this, update this wiki (it should be possible to do without this as firmware loading support is already present in the kernel).

Loading the modules

Assuming all the above succeeded you now need to load all modules on the slug.

Just issue the following commands on the slug:

  • cd /lib/modules/2.6.12.2
  • insmod ./kernel/drivers/media/video/v4l1-compat.ko
  • insmod ./kernel/drivers/media/video/v4l2-common.ko
  • insmod ./kernel/drivers/media/video/videodev.ko
  • insmod ./pvrusb2/firmware_class.ko
  • insmod ./pvrusb2/msp3400.ko
  • insmod ./pvrusb2/saa7115.ko
  • insmod ./pvrusb2/tveeprom.ko
  • insmod ./pvrusb2/tuner.ko
  • insmod ./pvrusb2/pvrusb2.ko (this one must be last!)
  • depmod -a

If insmod complains that a module is already loaded (e.g. tveeprom, or tuner) unload that one first (using rmmod).
For other errors look at the message log (using dmesg).

One issue is that when you reboot, the pvrusb2 module is not automatically reloaded. Fortunately there is an easy solution for this. As root do the following:

echo pvrusb2 >/etc/modutils/pvrusb2
update-modules

Loading the firmware

Next you'll need to extract the firmware. See details at the pvrusb2 Linux driver page. I used fwfind.sh (found in the utils section. The firmware was extracted from wintv_usb2_11_23074.exe. For some reason I had to do fwfind.sh twice to get the firmware files.

Extracting will give you two files: pvrusb2.f1 8192 bytes 8051 program image pvrusb2.f2 262144 bytes mpeg2 encoder image

On the slug, create the directory /lib/firmware and copy the two firmware files to this directory.

Next hotplug must be enabled. You might want to peek at OpenSlug/Hotplug for some more info on hotplug and how to enable it.

  • Create a directory /etc/hotplug.d/firmware
  • Create a file firmware.hotplug. Fill it with the contents as specified below. This is a renamed and slightly modified (pathnames) firmware.agent file.
  • Create a file hotplug.functions. Fill it with the contents as specified below. Alternately you could rip it from another system.
  • Make both files executable.

Making devices

Next you'll need to make the entries in /dev. I used a script called MAKEDEV.v4l that I got from the Video4Linux sources. However you can easily issue the needed mknod commands yourself. The major device number is 81, and actually you only need /dev/video0. The others (/dev/radio, /dev/vbi, /dev/vtx) are still unexplored territory.

Below is the full listing of major 81 on my system.
lrwxrwxrwx 1 root root 11 Sep 24 12:52 /dev/radio -> /dev/radio0
crw-rw-rw- 1 root root 81, 64 Sep 24 12:52 /dev/radio0
crw-rw-rw- 1 root root 81, 65 Sep 24 12:52 /dev/radio1
crw-rw-rw- 1 root root 81, 66 Sep 24 12:52 /dev/radio2
crw-rw-rw- 1 root root 81, 67 Sep 24 12:52 /dev/radio3
lrwxrwxrwx 1 root root 9 Sep 24 12:52 /dev/vbi -> /dev/vbi0
crw-rw-rw- 1 root root 81, 224 Sep 24 12:52 /dev/vbi0
crw-rw-rw- 1 root root 81, 225 Sep 24 12:52 /dev/vbi1
crw-rw-rw- 1 root root 81, 226 Sep 24 12:52 /dev/vbi2
crw-rw-rw- 1 root root 81, 227 Sep 24 12:52 /dev/vbi3
lrwxrwxrwx 1 root root 11 Sep 24 12:52 /dev/video -> /dev/video0
crw-rw-rw- 1 root root 81, 0 Sep 24 12:52 /dev/video0
crw-rw-rw- 1 root root 81, 1 Sep 24 12:52 /dev/video1
crw-rw-rw- 1 root root 81, 2 Sep 24 12:52 /dev/video2
crw-rw-rw- 1 root root 81, 3 Sep 24 12:52 /dev/video3
lrwxrwxrwx 1 root root 9 Sep 24 12:52 /dev/vtx -> /dev/vtx0
crw-rw-rw- 1 root root 81, 192 Sep 24 12:52 /dev/vtx0
crw-rw-rw- 1 root root 81, 193 Sep 24 12:52 /dev/vtx1
crw-rw-rw- 1 root root 81, 194 Sep 24 12:52 /dev/vtx2
crw-rw-rw- 1 root root 81, 195 Sep 24 12:52 /dev/vtx3

Testing your work

Testing is not very difficult.

  • Power the WinTV PVR USB2 using the supplied PSU. Make sure an antenna is connected with a good signal. Connect the WinTV PVR USB2 via USB to the USB port of a running and booted slug. Hotplug is used to load the modules and firmware, and loading the firmware at slug startup is still untested.
    After doing this you might want to do a dmesg | tail and check for the following lines at the end:
    pvrusb2 /*--TRACE_COMMIT--*/ "Channel" <-- 0 (<integer>)
    pvrusb2 /*--TRACE_COMMIT--*/ "Channel Program ID" <-- 0 (<integer>)
    pvrusb2 pvr2_stream_create: sp=c0ff4960
    pvrusb2 pvr2_hdw_setup: video stream is c0ff4960
    pvrusb2 pvr2_hdw_setup(hdw=c0f6d000) done, ok=1 init_ok=1
    pvrusb2 Device initialization completed successfully.
    pvrusb2 Registered pvrusb2 v4l device, minor=0
    If you got this the hotplugging worked and your driver modules are loaded.
    Next do the following (substituting sn-9508240 with whatever is in your pvrusb2 directory):
  • cd /sys/class/pvrusb2/sn-9508240/ctl_video_standard
  • make sure cur_val has the right value. If not check enum_val for a list of values and do echo newvalue >cur_val
  • cd /sys/class/pvrusb2/sn-9508240/ctl_frequency
  • Find a suitable frequency (not channel!) for your region and type echo frequency >cur_val. Note that frequency is in Hz, so it will look something like 528000000.
  • Type cat /dev/video0 >/tmp/slug.mpg
  • Hit ^C after 10 seconds or so
  • Copy /tmp/slug.mpg to a system where you can watch MPEG video (e.g. your Linux or Windows box) and see if it plays.

Report your results

If you manage to get this running, I'd like to hear from you. Please add your name to the list below and/or drop eFfeM an email (fransmeulenbroeks at yahoo dot com). In the evenings (CET+2) and weekends I might also be found on one of the IRC channels

People who got this working:
eFfeM
<yournamegoeshere>

firmware.hotplug

 
#!/bin/sh
#
# Firmware-specific hotplug policy agent.
#
# Kernel firmware hotplug params include:
#
#       ACTION=%s [add or remove]
#       DEVPATH=%s [in 2.5 kernels, /sys/$DEVPATH]
#       FIRMWARE=%s
#
# HISTORY:
#
# 24-Jul-2003   Initial version of "new" hotplug agent.
#
# $Id: firmware.agent,v 1.3 2004/03/14 15:52:56 ukai Exp $
#

cd /etc/hotplug.d/firmware
. ./hotplug.functions
# DEBUG=yes export DEBUG

# directory of the firmware files
FIRMWARE_DIR=/lib/firmware

# mountpoint of sysfs
SYSFS=$(sed -n 's/^.* \([^ ]*\) sysfs .*$/\1/p' /proc/mounts)

# use /proc for 2.4 kernels
if [ "$SYSFS" = "" ]; then
    SYSFS=/proc
fi

#
# What to do with this firmware hotplug event?
#
case "$ACTION" in

add)
    if [ ! -e $SYSFS/$DEVPATH/loading ]; then
        sleep 1
    fi

    if [ -f "$FIRMWARE_DIR/$FIRMWARE" ]; then
        echo 1 > $SYSFS/$DEVPATH/loading
        cp "$FIRMWARE_DIR/$FIRMWARE" $SYSFS/$DEVPATH/data
        ls -l "$FIRMWARE_DIR/$FIRMWARE" $SYSFS/$DEVPATH/data $SYSFS/$DEVPATH >>//LOG
        echo cp "$FIRMWARE_DIR/$FIRMWARE" $SYSFS/$DEVPATH/data >>/LOG
        echo 0 > $SYSFS/$DEVPATH/loading
    else
        echo -1 > $SYSFS/$DEVPATH/loading
    fi

    ;;

remove)
    ;;

*)
    mesg "Firmware '$ACTION' event not supported"
    exit 1
    ;;

esac

hotplug.functions

 
#
# Setup and BASH utility functions for use in hotplug agents
#
# Most essential parameters are passed from the kernel using
# environment variables.  For more information, see the docs
# on-line at http://linux-hotplug.sourceforge.net or the
# sources for each hotplug-aware kernel subsystem.
#
# $Id: hotplug.functions,v 1.26 2004/04/01 07:33:32 kroah Exp $
#
#

# DEBUG=yes; export DEBUG
PATH=/bin:/sbin:/usr/sbin:/usr/bin

KERNEL=`uname -r`
MODULE_DIR=/lib/modules/$KERNEL

HOTPLUG_DIR=/etc/hotplug

if [ -f /etc/sysconfig/hotplug ]; then
    . /etc/sysconfig/hotplug
fi

if [ -x /usr/bin/logger ]; then
    LOGGER=/usr/bin/logger
elif [ -x /bin/logger ]; then
    LOGGER=/bin/logger
else
    unset LOGGER
fi
#
# for diagnostics
#
if [ -t 1 -o -z "$LOGGER" ]; then
    mesg () {
	echo "$@"
    }
else
    mesg () {
	$LOGGER -t $(basename $0)"[$$]" "$@"
    }
fi

debug_mesg () {
    test "$DEBUG" = "" -o "$DEBUG" = no && return
    mesg "$@"
}


#
# Not "modprobe --autoclean" ... one driver module can handle many
# devices.  Unloading should be done when no devices are present.
# Autocleaning happens if none of the devices are open, once any of
# them gets opened; wrong timing.
#
MODPROBE="/sbin/modprobe -s -q"
#MODPROBE="/sbin/modprobe -vs"


####################################################################
#
# usage: load_driver type filename description
#
# modprobes driver module(s) if appropriate, and optionally
# invokes a driver-specific setup script (or user-mode driver).
#
# the "modules.*map" format file is guaranteed to exist
#
load_drivers ()
{
    local LOADED TYPE FILENAME DESCRIPTION LISTER
    DRIVERS=""

    # make this routine more readable
    TYPE=$1
    FILENAME=$2
    DESCRIPTION=$3

    # should we use usbmodules, pcimodules?  not on 2.5+, because sysfs
    # ought to expose the data we need to find all candidate drivers.
    # (on 2.5.48 it does for usb; but maybe not yet for pci.)
    case "$KERNEL" in
    2.2*|2.3*|2.4*)	LISTER=`which ${TYPE}modules` ;;
    *)			LISTER="" ;;
    esac

    if [ "$LISTER" != "" ]; then
	# lister programs MIGHT be preferable to parsing from shell scripts:
	# - usbmodules used for (a) multi-interface devices, (b) coldplug
	# - pcimodules used only for coldplug
	case $TYPE in
	usb)
	    # "usbutils-0.8" (or later) is needed in $PATH
	    # only works if we have usbfs
	    # ... reads more descriptors than are passed in env
	    # ... doesn't handle comment syntax either
	    if [ "$DEVICE" = "" -o ! -f "$DEVICE" ]; then
		LISTER=
	    else
		DRIVERS=`$LISTER --mapfile $FILENAME --device $DEVICE`
	    fi ;;

	pci)
	    debug_mesg "pcimodules is scanning more than $PCI_SLOT ..."
	    DRIVERS=`$LISTER`
	    ;;
	esac
    fi

    # try parsing by shell scripts if no luck yet
    if [ "$DRIVERS" = "" ]; then
	${TYPE}_map_modules < $FILENAME
    fi

    # FIXME remove dups and blacklisted modules from $DRIVERS here

    if [ "$DRIVERS" = "" ]; then
	return
    fi

    # Note that DRIVERS aren't all going to be modules.
    # For USB, some user-mode drivers or setup scripts may be listed.
    debug_mesg Setup $DRIVERS for $DESCRIPTION

    # either kernel or user mode drivers may need to be set up
    for MODULE in $DRIVERS
    do
	# maybe driver modules need loading
        LOADED=false
	if ! lsmod | grep -q "^$(echo $MODULE|sed -e 's/-/_/g') " > /dev/null 2>&1; then
	    if grep -q "^$MODULE\$" $HOTPLUG_DIR/blacklist \
		    >/dev/null 2>&1; then
		debug_mesg "... blacklisted module:  $MODULE"
		continue
	    fi

	    # statically linked modules aren't shown by 'lsmod',
	    # and user mode drivers will ONLY have a setup script;
	    # it's not an error if a module doesn't exist or won't load.
	    if $MODPROBE -n $MODULE >/dev/null 2>&1 &&
		    ! $MODPROBE $MODULE >/dev/null 2>&1 ; then
		mesg "... can't load module $MODULE"
	    else
		# /etc/modules.conf may have set non-default module
		# parameters ... handle per-device parameters in apps
		# (ioctls etc) not in setup scripts or modules.conf
		LOADED=true
	    fi
	else
	    # This module is already loaded
	    LOADED=true
	fi

	# always run setup scripts after any matching kernel code has had
	# a chance to do its thing, no matter whether it was dynamically
	# or statically linked, or if there is only a user mode driver.
	# the script might re-enumerate usb devices after firmware download,
	# giving kernel code another chance.
	if [ -x $HOTPLUG_DIR/$TYPE/$MODULE ]; then
	    debug_mesg Module setup $MODULE for $DESCRIPTION
	    $HOTPLUG_DIR/$TYPE/$MODULE
	    LOADED=true
	fi

	if [ "$LOADED" = "false" ]; then
	    mesg "missing kernel or user mode driver $MODULE "
	fi
	if echo "$MODULE" | grep -q "usb-storage" > /dev/null 2>&1 ; then
	    [ -x /usr/sbin/updfstab ] &&  /usr/sbin/updfstab
	fi
    done
}

####################################################################
#
# usage: log_to_stdout filename
#
# writes a copy of the current hotplug event to stdout.
# add buffering, to avoid interleaving reports!
#
log_to_stdout ()
{
    if [ -x /bin/date ]; then
	echo "HOTPLUG_TIME='$(/bin/date)'"
    fi

    env | egrep -v '^PATH=|^PWD=|^_=|^OLDPWD=|^SHLVL=|^HOME='
    echo ''
    # empty line terminates events
}

# vim:syntax=sh

Simplified instructions for OpenSlug 2.7 / 3.10

It seems that installation is now simpler than suggested by the above, as more things are included in the feed. The following worked for me:

use the same procedure for Openslug 3.10 but you can skip step 7. (Hotplug setup)

  1. Install OpenSlug 2.7
  2. Remove ANYTHING related to ntp. The combination PVR and ntp crashs the slug after some seconds. Killing ntp-related processes before connecting the PVR-Box does not solve this.
  3. ipkg install pvrusb2-mci kernel-module-v4l1-compat kernel-module-v4l2-common kernel-module-videodev kernel-module-firmware-class
  4. depmod -a
  5. modprobe pvrusb2
  6. Install firmware in /lib/firmware as above.
  7. Add /etc/hotplug.d/firmware/firmware.hotplug and /etc/hotplug.d/firmware/hotplug.functions as above (They must be executable).
  8. To test, cat /dev/video0 > /tmp/vid.mpeg

That's all there is to it.


This page is password protected.

The password is "wintv". Let's see if that stops the automated wiki spam.

Page last modified on June 14, 2007, at 09:34 PM