$Id: pvrusb2.html,v 1.16 2005/05/06 04:59:41 isely Exp $
Mike Isely <isely at pobox dot com>
The home location for this page is here.
This driver is intended for the Hauppauge WinTV PVR USB 2.0, which is a USB 2.0 hosted TV Tuner. Examples for sale can be found at pricegrabber.
This driver is very much a work in progress. Its history started with the reverse-engineering effort by Björn Danielsson whose web page can be found here. From there Aurelien Alleaume began an effort to create a video4linux compatible driver. His web page about this driver can be found here. Unfortunately it seems that Aurelien has stopped working on this driver. Repeated attempts to contact him over several months have not been successful. Thus I have for now taken Aurelien's latest snapshot and begun another round of changes. This page describes those efforts.
Latest driver snapshot:
pvrusb2-mci-20050505.tar.bz2
Older snapshots (version format is yyyymmdd):
pvrusb2-mci-20050430.tar.bz2 pvrusb2-mci-20050427.tar.bz2
pvrusb2-mci-20050423.tar.bz2
pvrusb2-mci-20050421.tar.bz2
pvrusb2-mci-20050313.tar.bz2
pvrusb2-mci-20050227.tar.bz2
Drop me a message (address at top of page) and I'll add you to a notification list for driver updates.
This driver only works under Linux 2.6.x. I have not made any attempt to even try it in 2.4.x and I know there are environmental differences which likely prevent it from running or even loading.
The WinTV-PVR-USB-2.0 tuner is a device containing an 8051 microcontroller and another programmable part (either the FPGA or the cx23416 mpeg2 encoder, not exactly sure), both of which must be loaded with vendor firmware before the driver will run. That firmware is not included here; you must extract it from the Windows driver package that came with your device and then place that firmware in a location where the hotplug system can find it. The best instructions for doing this can be found on Björn's web page (see above).
You MUST ensure that your kernel has been configured and built such that tveeprom.ko, tuner.ko, and msp3400.ko are all built and available. This driver relies on those modules. Failure to build tveeprom.ko should cause an immediate load error. But the other two modules are bound late into the driver via the I2C abstraction layer so their absence will be harder to figure out.
This driver has been tested against 2.6.10-ac12 and 2.6.11.7 with the "-3" v4l release applied against it. Probably you will need something at least this recent.
Compile this driver in the usual way one does to build 2.6.x kernel modules outside of the kernel source tree. Said another way, run "make" with KREL set to the version of the kernel you intend to use (e.g. output of uname -r), and KDIR set to the root directory where you have the kernel sources installed (e.g. /lib/modules/$(KREL)/source).
Once you have the driver compiled, copy *.ko (note that there are multiple files) into /lib/modules/$(KREL)/misc and then run depmod -a so that the module loader will recognize any needed dependencies.
You can next execute modprobe pvrusb2 to load the driver. After this point, lsmod should show pvrusb2, tveeprom, tuner, msp3400, and saa7115 all present. With hotplug running, this step is not strictly needed, as hotplug will do the needed module loading when the device appears in the system.
Plug in your WinTV-PVR-USB-2.0 device and after a few seconds the driver should be ready to go. Progress can be noticed by watching the kernel log.
Note that the level of log verbosity is controlled through a global bit mask variable whose name is debug. This mask is set initially at compile time from within pvrusb2-main.c, using defined values found in pvrusb2-debug.h. There supposedly exists the ability to adjust the debug mask at run-time through a Sysfs variable in the driver's control directory - this I understand is a standard feature for modules which export parameters. However I haven't tried that yet.
If the driver isn't loaded when you plug in the device, that's OK because if you're running hotplug, then the driver should be automatically found and loaded for you.
It should be safe to attempt to remove (i.e. modprobe -r) the driver at any time, in any state. If the device is idle, the driver will be removed, even if it is still plugged in. If the device is not idle, then its non-zero kernel reference count should cause the removal operation to fail in an obvious way.
This driver provides an implementation of the video4linux driver API. Any v4l application which can handle an mpeg2 stream should in theory be able to use this driver. You can test it by running xawtv 4.x. Note that anything before version 4 will not work with this since earlier versions did not support mpeg2 decoding. Obviously, make sure you've built xawtv with mpeg2 video and mp3 audio support configured into it.
There is an additional interface available with this driver. In parallel with the v4l interface, you can now access all driver controls via sysfs. Once the device is plugged in and the driver is loaded, try this:
# cd /sys/class/pvrusb2/sn-XXXX
where XXXX is the serial number of your device (just let tab-completion do the hard work here since unless you have multiple tuners there will only be one file there). Now use "ls" and you'll see a whole bunch of directories all starting with "ctl_". Here is what my system looks like:
londo:~# cd /sys/class/pvrusb2/sn-6829718/ londo:/sys/class/pvrusb2/sn-6829718# ls ctl_audio_bitrate ctl_frequency ctl_treble ctl_audio_crc ctl_hue ctl_vbr ctl_audio_emphasis ctl_input ctl_video_average_bitrate ctl_audio_layer ctl_interlace ctl_video_peak_bitrate ctl_audio_mode ctl_mute ctl_video_standard ctl_balance ctl_resolution_hor ctl_volume ctl_bass ctl_resolution_ver device ctl_brightness ctl_saturation driver ctl_contrast ctl_srate londo:/sys/class/pvrusb2/sn-6829718#
(The device and driver links you see there by the way point off to other parts of sysfs where the driver's and device's lower level control files can be found.)
Each ctl_ directory has some subset of these files:
You can read any of these files just by cat'ing it out. All are read-only except for cur_val, which can be set by just writing the new value into it. The incoming value must be either a legal enumeration constant (for enumerated controls) or an integer within the legal range specified by min_val and max_val in order for the assignment to "take". Otherwise the program doing the write should get back an EINVAL error status.
I put together this interface to make it easier to debug the driver, independant of an application like xawtv. The possibilities here are obvious. For example, it should be possible open the /dev/ entry into mplayer and then completely control everything else with this sysfs interface while mplayer is running. One could write a control program in Perl with this interface...
Please be aware that with this interface one has complete run of all the driver's controls. There are certainly combinations of settings which, uh, won't work very well. For example, changing the capture resolution is not a pathway very well trodden yet. But as I said, I put this here to make it easier to debug the driver. It was either this or invent a pile of new ioctl()'s and write a test program to operate those settings (the ioctl() approach I believe is what ivtv does).
The IR receiver within the device is an I2C part that is understood by the lircd software package (0.7 or later). Previously Aurelien's driver hardcoded something here which made the IR receiver into another source for /dev/input, but I had stability problems with this and just decided to rip it out in favor of letting more stable external software handle this function.
I have not tested the IR receiver yet, but given its nature, you should be able to do here precisely the same solution as that needed for ivtv. In other words, grab lircd 0.7 or later, build it, modprobe the I2C driver into the kernel and when configured with the appropriate lircd.conf (one is included with the pvrusb2 driver), it should "just work". The I2C driver should discover the internal I2C bus made available by the pvrusb2 driver, probe that bus, and attach itself when it finds the IR receiver chip it will be looking for.
I would appreciate a report from anyone who confirms that this indeed does work.
There is a frequency table implemented inside this driver. It is not available for v4l, but it can be used with the sysfs control interface. You must program it first before using it, but once programmed it becomes possible to change the channel just by, well, writing the new channel number to the driver. The table size is currently limited to channel numbers 1 through 500 (far in excess of anything anyone should need), and the channel ids must be integers not something cute like station call letters.
The frequency table must be programmed a slot at a time. You do this by first selecting the slot's id (a.k.a. the channel number) into the "freq_table_channel" variable through sysfs. Once selected, you can read / write the frequency (in Hz) for that slot using the "freq_table_value" variable through sysfs. Repeat this process for all channels to be programmed. Yes, this is just begging for a shell script to do the dirty work. Anyone care to write one?
Once you've programmed the desired slots in the table, just "change the channel" by writing the desired channel number to the "channel" variable through sysfs. That's it.
The frequency can still be set as before by writing the actual frequency to the "frequency" variable. If that is done, then the "channel" will be implicitly set to zero, which means "none". Thus the channel and frequency variables at all times stay consistent with each other and there's no loss of flexible or any implied confusion.
The frequency variable can of course be read back at any time to see what the actual frequency is, regardless of whether it was set directly or implied by a channel setting. And of course the channel variable can be read back at any time to find out what the current channel is or if it is not being used due to the frequency being directly set (in which case the value read back will be zero).
Why do this? Well it was dirt-cheap easy to implement, and it does help with debugging, though in a minor way. Besides it's cool to do. OK, OK. Enough playing and back to the real rework...
Aurelien's version of this driver implemented all chip-level functionality directly inside the pvrusb2 source code. All these chips are accessed via an internal I2C bus, and it so happens that the Linux kernel has a fairly decent I2C abstraction layer in it. In addition, there already exist more complete and better-tested chip level drivers out there that use this I2C abstraction layer. So the first thing I did was to implement a proper I2C adapter driver within pvrusb2, and then (similar to the IR remote description earlier) I proceeded to rip out the redundant code in favor of using the better external implementations. The external chip-level drivers currently being used are:
Even though the PVR USB2 is a USB device while everything else driven by ivtv is a PCI device, there really is more than a passing resemblance among them. As such it's no coincidence that all the listed chip-level drivers above also happen to be in ivtv. (In fact, the same NDA-protected, no-datasheet-available cx23416 mpeg2 encoder - which is the heart of ivtv - is also used in this device.) If you have / need to also use ivtv, it should be possible for this driver to coexist with it. You can discard the saa7115.ko driver from this package in favor of the one from ivtv (which likely will have additional fixes). Though msp3400.ko in ivtv is considerably different than the one in v4l, they both work fine with this driver, so this driver isn't affected by that issue. The ivtv tuner.ko module has not been tested with this driver, but a source code inspection suggests that they are similar enough that it should not be a problem. That leaves tveeprom.ko, which unfortunately is not compatible between ivtv and v4l. This driver binds that module directly at load time, so in theory you can probably work around this by compiling v4l's tveeprom directly into the kernel, but it hasn't been tried. In any case, this issue is no worse than any other v4l module which needs to use v4l's tveeprom.ko in the presence of ivtv.
The X-box has an internal I2C bus, and unfortunately the code that was hacked together for it makes the assumption that it is the only I2C bus that can possibly exist on an xbox. That assumption becomes false when a PVR USB2 device is introduced, unfortunately. The problem here is that the I2C driver code for the xbox tries to attach to the PVR USB2's I2C bus, causing dangling pointers in the xbox driver code and chaos ensues. If you have an xbox, I have a patch for the xbox I2C driver code that makes it play nicer (it's still a horrible hack though). I will try to get that code submitted back to the xbox author(s). In the mean time, contact me for the patch.
It seems that the v4l implementation is still undergoing significant development. There's a risk that a later snapshot may cause this driver to break. Indeed, it is already known that you need at least 2.6.10-3 of the v4l kernel patch for the driver to even work. There isn't anything really that can be done here yet about this problem, except to warn the reader to watch out for trouble.
pvrusb2-mci-20050505
pvrusb2-mci-20050430
pvrusb2-mci-20050427
pvrusb2-mci-20050423
pvrusb2-mci-20050421
pvrusb2-mci-20050313
pvrusb2-mci-20050311
pvrusb2-mci-20050227
pvrusb2-mci-20050217
(Aurelien's 07112004 snapshot starting point)
This is a very immature driver. There are a number of issues. However since they change with each driver snapshot, please see the README file included in the snapshot sources for a list of known issues.
Feel free to e-mail me (address at the top of this page) if you have any questions or just want to say hello...
Mike Isely