diff options
author | Alex Woods <devnull@localhost> | 2004-01-12 21:41:41 +0000 |
---|---|---|
committer | Alex Woods <devnull@localhost> | 2004-01-12 21:41:41 +0000 |
commit | 2d7fbe39b4d518dad90974c3fff93a77ae78f6c1 (patch) | |
tree | a121f3d721437a6095065911eaf27e08d55732ec /linux | |
parent | d451c42a3fd22b92c5f562c7f60a95f61fa744fc (diff) | |
download | mediapointer-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.txt | 19 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c | 152 |
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"); |