Skip to content

Commit

Permalink
V4L/DVB (11096): V4L2 Driver for the Hauppauge HD PVR usb capture device
Browse files Browse the repository at this point in the history
The device encodes component video up to 1080i to a MPEG-TS stream with
H.264 video and stereo AAC audio. Newer firmwares accept also AC3
(up to 5.1) audio over optical SPDIF without reencoding.
Firmware upgrade is unimplemeted but rather unimportant since
the firmware sits on a flash chip.

The I2C adapter to drive the integrated infrared receiver/sender is
currently disabled due to a conflict with cx18-based devices.

Tested-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Janne Grunau <j@jannau.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Janne Grunau authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent 8c84cfd commit 9aba42e
Show file tree
Hide file tree
Showing 10 changed files with 2,333 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/media/video/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,8 @@ source "drivers/media/video/gspca/Kconfig"

source "drivers/media/video/pvrusb2/Kconfig"

source "drivers/media/video/hdpvr/Kconfig"

source "drivers/media/video/em28xx/Kconfig"

source "drivers/media/video/usbvision/Kconfig"
Expand Down
2 changes: 2 additions & 0 deletions drivers/media/video/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ obj-$(CONFIG_USB_PWC) += pwc/
obj-$(CONFIG_USB_ZC0301) += zc0301/
obj-$(CONFIG_USB_GSPCA) += gspca/

obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/

obj-$(CONFIG_USB_IBMCAM) += usbvideo/
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
Expand Down
10 changes: 10 additions & 0 deletions drivers/media/video/hdpvr/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

config VIDEO_HDPVR
tristate "Hauppauge HD PVR support"
depends on VIDEO_DEV
---help---
This is a video4linux driver for Hauppauge's HD PVR USB device.

To compile this driver as a module, choose M here: the
module will be called hdpvr

7 changes: 7 additions & 0 deletions drivers/media/video/hdpvr/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o

obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o

EXTRA_CFLAGS += -Idrivers/media/video

EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
201 changes: 201 additions & 0 deletions drivers/media/video/hdpvr/hdpvr-control.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Hauppage HD PVR USB driver - video 4 linux 2 interface
*
* Copyright (C) 2008 Janne Grunau (j@jannau.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/mutex.h>

#include <linux/videodev2.h>

#include <media/v4l2-common.h>

#include "hdpvr.h"


int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
{
int ret;
char request_type = 0x38, snd_request = 0x01;

msleep(10);

mutex_lock(&dev->usbc_mutex);
dev->usbc_buf[0] = valbuf;
ret = usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
snd_request, 0x00 | request_type,
value, CTRL_DEFAULT_INDEX,
dev->usbc_buf, 1, 10000);

mutex_unlock(&dev->usbc_mutex);
dev_dbg(&dev->udev->dev,
"config call request for value 0x%x returned %d\n", value,
ret);

return ret < 0 ? ret : 0;
}

struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
{
struct hdpvr_video_info *vidinf = NULL;
#ifdef HDPVR_DEBUG
char print_buf[15];
#endif
int ret;

vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
if (!vidinf) {
dev_err(&dev->udev->dev, "out of memory");
goto err;
}

mutex_lock(&dev->usbc_mutex);
ret = usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
0x81, 0x80 | 0x38,
0x1400, 0x0003,
dev->usbc_buf, 5,
1000);
if (ret == 5) {
vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
vidinf->fps = dev->usbc_buf[4];
}

#ifdef HDPVR_DEBUG
if (hdpvr_debug & MSG_INFO) {
hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf,
sizeof(print_buf), 0);
dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n",
ret, print_buf);
}
#endif
mutex_unlock(&dev->usbc_mutex);

if (!vidinf->width || !vidinf->height || !vidinf->fps) {
kfree(vidinf);
vidinf = NULL;
}
err:
return vidinf;
}

int get_input_lines_info(struct hdpvr_device *dev)
{
#ifdef HDPVR_DEBUG
char print_buf[9];
#endif
int ret, lines;

mutex_lock(&dev->usbc_mutex);
ret = usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
0x81, 0x80 | 0x38,
0x1800, 0x0003,
dev->usbc_buf, 3,
1000);

#ifdef HDPVR_DEBUG
if (hdpvr_debug & MSG_INFO) {
hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf,
sizeof(print_buf), 0);
dev_dbg(&dev->udev->dev,
"get input lines info returned: %d, %s\n", ret,
print_buf);
}
#endif
lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
mutex_unlock(&dev->usbc_mutex);
return lines;
}


int hdpvr_set_bitrate(struct hdpvr_device *dev)
{
int ret;

mutex_lock(&dev->usbc_mutex);
memset(dev->usbc_buf, 0, 4);
dev->usbc_buf[0] = dev->options.bitrate;
dev->usbc_buf[2] = dev->options.peak_bitrate;

ret = usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
0x01, 0x38, CTRL_BITRATE_VALUE,
CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000);
mutex_unlock(&dev->usbc_mutex);

return ret;
}

int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
enum v4l2_mpeg_audio_encoding codec)
{
int ret = 0;

if (dev->flags & HDPVR_FLAG_AC3_CAP) {
mutex_lock(&dev->usbc_mutex);
memset(dev->usbc_buf, 0, 2);
dev->usbc_buf[0] = input;
if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC)
dev->usbc_buf[1] = 0;
else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3)
dev->usbc_buf[1] = 1;
else {
mutex_unlock(&dev->usbc_mutex);
dev_err(&dev->udev->dev, "invalid audio codec %d\n",
codec);
ret = -EINVAL;
goto error;
}

ret = usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
0x01, 0x38, CTRL_AUDIO_INPUT_VALUE,
CTRL_DEFAULT_INDEX, dev->usbc_buf, 2,
1000);
mutex_unlock(&dev->usbc_mutex);
if (ret == 2)
ret = 0;
} else
ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE,
dev->options.audio_input+1);
error:
return ret;
}

int hdpvr_set_options(struct hdpvr_device *dev)
{
hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std);

hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE,
dev->options.video_input+1);

hdpvr_set_audio(dev, dev->options.audio_input+1,
dev->options.audio_codec);

hdpvr_set_bitrate(dev);
hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
dev->options.bitrate_mode);
hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode);

hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness);
hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast);
hdpvr_config_call(dev, CTRL_HUE, dev->options.hue);
hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation);
hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness);

return 0;
}
Loading

0 comments on commit 9aba42e

Please sign in to comment.