summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorAlex Woods <devnull@localhost>2004-01-12 21:41:41 +0000
committerAlex Woods <devnull@localhost>2004-01-12 21:41:41 +0000
commit2d7fbe39b4d518dad90974c3fff93a77ae78f6c1 (patch)
treea121f3d721437a6095065911eaf27e08d55732ec /linux
parentd451c42a3fd22b92c5f562c7f60a95f61fa744fc (diff)
downloadmediapointer-dvb-s2-2d7fbe39b4d518dad90974c3fff93a77ae78f6c1.tar.gz
mediapointer-dvb-s2-2d7fbe39b4d518dad90974c3fff93a77ae78f6c1.tar.bz2
Support DEC2540-t under kernel 2.4 and add info on it to the ttusb-dec docs.
Add a module option to get the raw AVPES packets from the dvr device. Handle the new empty packets that appear with the 2.16 firmware. Extra error checks.
Diffstat (limited to 'linux')
-rw-r--r--linux/Documentation/dvb/ttusb-dec.txt19
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c152
2 files changed, 127 insertions, 44 deletions
diff --git a/linux/Documentation/dvb/ttusb-dec.txt b/linux/Documentation/dvb/ttusb-dec.txt
index a844d8e09..1eca96907 100644
--- a/linux/Documentation/dvb/ttusb-dec.txt
+++ b/linux/Documentation/dvb/ttusb-dec.txt
@@ -14,6 +14,7 @@ Supported:
Hotplug firmware loader under 2.6 kernels
In Progress:
+ DEC2540-t
DEC3000-s
To Do:
@@ -23,11 +24,13 @@ To Do:
Getting the Firmware
--------------------
-The firmware can be found in the software update files on this page:
+The firmware can be found in the software update zip files on this page:
http://www.hauppauge.de/sw_dec.htm
-The firmware for the DEC2000-t is called STB_PC_T.bin, and the firmware for
-the DEC3000-s is called STB_PC_S.bin.
+The firmwares are named as follows:
+DEC2000-t: STB_PC_T.bin
+DEC2540-t: STB_PC_X.bin
+DEC3000-s: STB_PC_S.bin
Note that firmwares since version 2.16 beta2 for the DEC2000-t give the device
the USB ID of the DEC3000-s. The driver copes with this.
@@ -36,16 +39,19 @@ Instructions follow for retrieving version 2.16 of the firmware:
wget http://hauppauge.lightpath.net/de/dec216.exe
unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_T.bin
+unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_X.bin
unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_S.bin
Compilation Notes for 2.4 kernels
---------------------------------
For 2.4 kernels the firmware for the DECs is compiled into the driver itself.
-The firmwares are expected to be in /etc/dvb at compilation time.
+The firmwares are expected to be in the build-2.4 directory at compilation
+time.
-mv STB_PC_T.bin /etc/dvb/dec2000t.bin
-mv STB_PC_S.bin /etc/dvb/dec3000s.bin
+mv STB_PC_T.bin build-2.4/dec2000t.bin
+mv STB_PC_X.bin build-2.4/dec2540t.bin
+mv STB_PC_S.bin build-2.4/dec3000s.bin
Hotplug Firmware Loading for 2.6 kernels
@@ -54,4 +60,5 @@ For 2.6 kernels the firmware is loaded at the point that the driver module is
loaded. See linux/Documentation/dvb/firmware.txt for more information.
mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t.fw
+mv STB_PC_X.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2540t.fw
mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s.fw
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index b2df5535f..a75509993 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -41,6 +41,7 @@
#include "dvb_net.h"
static int debug = 0;
+static int output_avpes = 0;
#define dprintk if (debug) printk
@@ -48,14 +49,15 @@ static int debug = 0;
#define COMMAND_PIPE 0x03
#define RESULT_PIPE 0x84
-#define STREAM_PIPE 0x88
+#define IN_PIPE 0x88
+#define OUT_PIPE 0x07
#define COMMAND_PACKET_SIZE 0x3c
#define ARM_PACKET_SIZE 0x1000
#define ISO_BUF_COUNT 0x04
#define FRAMES_PER_ISO_BUF 0x04
-#define ISO_FRAME_SIZE 0x0380
+#define ISO_FRAME_SIZE 0x03FF
#define MAX_AV_PES_LENGTH 6144
@@ -69,14 +71,22 @@ enum ttusb_dec_model {
};
enum ttusb_dec_packet_type {
- PACKET_AV_PES,
- PACKET_SECTION
+ TTUSB_DEC_PACKET_AV_PES,
+ TTUSB_DEC_PACKET_SECTION,
+ TTUSB_DEC_PACKET_EMPTY
+};
+
+enum ttusb_dec_interface {
+ TTUSB_DEC_INTERFACE_INITIAL,
+ TTUSB_DEC_INTERFACE_IN,
+ TTUSB_DEC_INTERFACE_OUT
};
struct ttusb_dec {
enum ttusb_dec_model model;
char *model_name;
char *firmware_name;
+ int can_playback;
/* DVB bits */
struct dvb_adapter *adapter;
@@ -92,13 +102,14 @@ struct ttusb_dec {
int hi_band;
/* USB bits */
- struct usb_device *udev;
- u8 trans_count;
- unsigned int command_pipe;
- unsigned int result_pipe;
- unsigned int stream_pipe;
- int interface;
- struct semaphore usb_sem;
+ struct usb_device *udev;
+ u8 trans_count;
+ unsigned int command_pipe;
+ unsigned int result_pipe;
+ unsigned int in_pipe;
+ unsigned int out_pipe;
+ enum ttusb_dec_interface interface;
+ struct semaphore usb_sem;
void *iso_buffer;
dma_addr_t iso_dma_handle;
@@ -111,6 +122,7 @@ struct ttusb_dec {
int packet_state;
int packet_length;
int packet_payload_length;
+ u16 next_packet_id;
int av_pes_stream_count;
int filter_stream_count;
@@ -336,6 +348,13 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec *dec, u8 *av_pes,
return;
}
+ if (output_avpes) {
+ dec->av_filter->feed->cb.ts(av_pes, length, 0, 0,
+ &dec->av_filter->feed->feed.ts,
+ DMX_OK);
+ return;
+ }
+
switch (av_pes[2]) {
case 0x01: { /* VideoStream */
@@ -439,6 +458,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
{
int i;
u16 csum = 0;
+ u16 packet_id;
if (dec->packet_length % 2) {
printk("%s: odd sized packet - discarding\n", __FUNCTION__);
@@ -453,18 +473,34 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
return;
}
+ packet_id = dec->packet[dec->packet_length - 4] << 8;
+ packet_id += dec->packet[dec->packet_length - 3];
+
+ if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
+ printk("%s: warning: lost packets between %u and %u\n",
+ __FUNCTION__, dec->next_packet_id - 1, packet_id);
+ }
+
+ if (packet_id == 0xffff)
+ dec->next_packet_id = 0x8000;
+ else
+ dec->next_packet_id = packet_id + 1;
+
switch (dec->packet_type) {
- case PACKET_AV_PES:
+ case TTUSB_DEC_PACKET_AV_PES:
if (dec->av_pes_stream_count)
ttusb_dec_process_av_pes(dec, dec->packet,
dec->packet_payload_length);
break;
- case PACKET_SECTION:
+ case TTUSB_DEC_PACKET_SECTION:
if (dec->filter_stream_count)
ttusb_dec_process_filter(dec, dec->packet,
dec->packet_payload_length);
break;
+
+ case TTUSB_DEC_PACKET_EMPTY:
+ break;
}
}
@@ -513,15 +549,25 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
case 4:
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_length == 3) {
+ if (dec->packet_length == 2) {
if (dec->packet[0] == 'A' &&
dec->packet[1] == 'V') {
- dec->packet_type = PACKET_AV_PES;
+ dec->packet_type =
+ TTUSB_DEC_PACKET_AV_PES;
dec->packet_state++;
} else if (dec->packet[0] == 'S') {
- dec->packet_type = PACKET_SECTION;
+ dec->packet_type =
+ TTUSB_DEC_PACKET_SECTION;
dec->packet_state++;
+ } else if (dec->packet[0] == 0x00) {
+ dec->packet_type =
+ TTUSB_DEC_PACKET_EMPTY;
+ dec->packet_payload_length = 2;
+ dec->packet_state = 7;
} else {
+ printk("%s: unknown packet type: "
+ "%02x%02x\n", __FUNCTION__,
+ dec->packet[0], dec->packet[1]);
dec->packet_state = 0;
}
}
@@ -532,13 +578,14 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
case 5:
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_type == PACKET_AV_PES &&
+ if (dec->packet_type == TTUSB_DEC_PACKET_AV_PES &&
dec->packet_length == 8) {
dec->packet_state++;
dec->packet_payload_length = 8 +
(dec->packet[6] << 8) +
dec->packet[7];
- } else if (dec->packet_type == PACKET_SECTION &&
+ } else if (dec->packet_type ==
+ TTUSB_DEC_PACKET_SECTION &&
dec->packet_length == 5) {
dec->packet_state++;
dec->packet_payload_length = 5 +
@@ -575,7 +622,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_type == PACKET_SECTION &&
+ if (dec->packet_type == TTUSB_DEC_PACKET_SECTION &&
dec->packet_payload_length % 2)
tail++;
@@ -690,7 +737,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
urb->dev = dec->udev;
urb->context = dec;
urb->complete = ttusb_dec_process_urb;
- urb->pipe = dec->stream_pipe;
+ urb->pipe = dec->in_pipe;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
urb->transfer_flags = URB_ISO_ASAP;
urb->interval = 1;
@@ -734,12 +781,30 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
* for a short period, so it's important not to call this function just before
* trying to talk to it.
*/
-static void ttusb_dec_set_streaming_interface(struct ttusb_dec *dec)
+static int ttusb_dec_set_interface(struct ttusb_dec *dec,
+ enum ttusb_dec_interface interface)
{
- if (!dec->interface) {
- usb_set_interface(dec->udev, 0, 8);
- dec->interface = 8;
+ int result = 0;
+
+ if (interface != dec->interface) {
+ switch (interface) {
+ case TTUSB_DEC_INTERFACE_INITIAL:
+ result = usb_set_interface(dec->udev, 0, 0);
+ break;
+ case TTUSB_DEC_INTERFACE_IN:
+ result = usb_set_interface(dec->udev, 0, 7);
+ break;
+ case TTUSB_DEC_INTERFACE_OUT:
+ result = usb_set_interface(dec->udev, 0, 1);
+ break;
+ }
+
+ if (result)
+ return result;
+
+ dec->interface = interface;
}
+ return 0;
}
static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
@@ -754,6 +819,10 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
if (!dec->iso_stream_count) {
ttusb_dec_setup_urbs(dec);
+ dec->packet_state = 0;
+ dec->v_pes_postbytes = 0;
+ dec->next_packet_id = 0;
+
for (i = 0; i < ISO_BUF_COUNT; i++) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if ((result = usb_submit_urb(dec->iso_urb[i],
@@ -773,9 +842,6 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
return result;
}
}
-
- dec->packet_state = 0;
- dec->v_pes_postbytes = 0;
}
dec->iso_stream_count++;
@@ -783,7 +849,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
up(&dec->iso_sem);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- ttusb_dec_set_streaming_interface(dec);
+ ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
#endif
return 0;
@@ -794,6 +860,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct ttusb_dec *dec = dvbdmx->priv;
u8 b0[] = { 0x05 };
+ int result = 0;
dprintk("%s\n", __FUNCTION__);
@@ -848,12 +915,12 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
}
- ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+ result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+ if (result)
+ return result;
dec->av_pes_stream_count++;
- ttusb_dec_start_iso_xfer(dec);
-
- return 0;
+ return ttusb_dec_start_iso_xfer(dec);
}
static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -903,9 +970,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
dvbdmxfeed->priv = finfo;
dec->filter_stream_count++;
- ttusb_dec_start_iso_xfer(dec);
-
- return 0;
+ return ttusb_dec_start_iso_xfer(dec);
}
return -EAGAIN;
@@ -1078,13 +1143,15 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
- dec->stream_pipe = usb_rcvisocpipe(dec->udev, STREAM_PIPE);
+ dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
+ dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
ttusb_dec_alloc_iso_urbs(dec);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include "dsp_dec2000t.h"
+#include "dsp_dec2540t.h"
#include "dsp_dec3000s.h"
#endif
@@ -1121,11 +1188,15 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
#else
switch (dec->model) {
case TTUSB_DEC2000T:
- case TTUSB_DEC2540T:
firmware = &dsp_dec2000t[0];
firmware_size = sizeof(dsp_dec2000t);
break;
+ case TTUSB_DEC2540T:
+ firmware = &dsp_dec2540t[0];
+ firmware_size = sizeof(dsp_dec2540t);
+ break;
+
case TTUSB_DEC3000S:
firmware = &dsp_dec3000s[0];
firmware_size = sizeof(dsp_dec3000s);
@@ -1245,6 +1316,9 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
break;
}
+ if (version >= 0x01770000)
+ dec->can_playback = 1;
+
return 0;
}
}
@@ -1698,7 +1772,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
return (void *)dec;
#else
- ttusb_dec_set_streaming_interface(dec);
+ ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
return 0;
#endif
@@ -1801,3 +1875,5 @@ MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug level");
+MODULE_PARM(output_avpes, "i");
+MODULE_PARM_DESC(output_avpes, "Output AVPES from dvr device");