summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/Documentation/dvb/contributors.txt6
-rw-r--r--linux/Documentation/dvb/ttusb-dec.txt16
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c113
3 files changed, 111 insertions, 24 deletions
diff --git a/linux/Documentation/dvb/contributors.txt b/linux/Documentation/dvb/contributors.txt
index 923d937cd..86c9270da 100644
--- a/linux/Documentation/dvb/contributors.txt
+++ b/linux/Documentation/dvb/contributors.txt
@@ -8,7 +8,7 @@ Christian Theiss
Marcus Metzler <mocm@metzlerbros.de>
Ralph Metzler <rjkm@metzlerbros.de>
- for their contining work on the DVB driver
+ for their continuing work on the DVB driver
Michael Holzt <kju@debian.org>
for his contributions to the dvb-net driver
@@ -58,5 +58,9 @@ Davor Emard <emard@softhome.net>
for his work on the budget drivers, the demux code,
the module unloading problems, ...
+Hans-Frieder Vogt <hfvogt@arcor.de>
+ for his work on calculating and checking the crc's for the
+ TechnoTrend/Hauppauge DEC driver firmware
+
(If you think you should be in this list, but you are not, drop a
line to the DVB mailing list)
diff --git a/linux/Documentation/dvb/ttusb-dec.txt b/linux/Documentation/dvb/ttusb-dec.txt
index e2fefb6dc..7e3f2beac 100644
--- a/linux/Documentation/dvb/ttusb-dec.txt
+++ b/linux/Documentation/dvb/ttusb-dec.txt
@@ -23,8 +23,16 @@ To Do:
Getting the Firmware
--------------------
-Currently, the driver only works with v2.15a of the firmware. The firmwares
-can be obtained in this way:
+The firmware can be found in the software update 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.
+
+Note that firmware version 2.16 beta2 for the DEC2000-t has a bug that sets
+the device's USB id to that of the DEC3000-s, making it unusable.
+
+Instructions follow for retrieving version 2.15a of the firmware:
wget http://hauppauge.lightpath.net/de/dec215a.exe
unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin
@@ -45,5 +53,5 @@ Hotplug Firmware Loading for 2.6 kernels
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-2.15a.fw
-mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s-2.15a.fw
+mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t.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 2fcd2887b..75b9f3c10 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -20,6 +20,7 @@
*/
#include <asm/semaphore.h>
+#include <linux/crc32.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -168,6 +169,19 @@ static struct dvb_frontend_info dec3000s_frontend_info = {
FE_CAN_HIERARCHY_AUTO,
};
+static u16 crc16(u16 crc, const u8 *buf, size_t len)
+{
+ u16 tmp;
+
+ while (len--) {
+ crc ^= *buf++;
+ crc ^= (u8)crc >> 4;
+ tmp = (u8)crc;
+ crc ^= (tmp ^ (tmp << 1)) << 4;
+ }
+ return crc;
+}
+
static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
@@ -235,6 +249,40 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
}
}
+static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
+ unsigned int *product,
+ unsigned int *version)
+{
+ u8 c[COMMAND_PACKET_SIZE];
+ int c_length;
+ int result;
+ unsigned int tmp;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+ if (result)
+ return result;
+
+ if (c_length >= 0x0c) {
+ if (mode != NULL) {
+ memcpy(&tmp, c, 4);
+ *mode = ntohl(tmp);
+ }
+ if (product != NULL) {
+ memcpy(&tmp, &c[4], 4);
+ *product = ntohl(tmp);
+ }
+ if (version != NULL) {
+ memcpy(&tmp, &c[8], 4);
+ *version = ntohl(tmp);
+ }
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
{
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)priv;
@@ -1038,14 +1086,16 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
int i, j, actual_len, result, size, trans_count;
u8 b0[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00 };
+ 0x61, 0x00 };
u8 b1[] = { 0x61 };
u8 b[ARM_PACKET_SIZE];
+ char idstring[21];
u8 *firmware = NULL;
size_t firmware_size = 0;
- u32 firmware_csum = 0;
+ u16 firmware_csum = 0;
+ u16 firmware_csum_ns;
u32 firmware_size_nl;
- u32 firmware_csum_nl;
+ u32 crc32_csum, crc32_check, tmp;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
const struct firmware *fw_entry = NULL;
#endif
@@ -1061,29 +1111,47 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
firmware = fw_entry->data;
firmware_size = fw_entry->size;
-#endif
+#else
switch (dec->model) {
case TTUSB_DEC2000T:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
firmware = &dsp_dec2000t[0];
firmware_size = sizeof(dsp_dec2000t);
-#endif
- firmware_csum = 0x1bc86100;
break;
case TTUSB_DEC3000S:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
firmware = &dsp_dec3000s[0];
firmware_size = sizeof(dsp_dec3000s);
-#endif
- firmware_csum = 0x00000000;
break;
}
+#endif
+
+ if (firmware_size < 60) {
+ printk("%s: firmware size too small for DSP code (%u < 60).\n",
+ __FUNCTION__, firmware_size);
+ return -1;
+ }
+
+ /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
+ at offset 56 of file, so use it to check if the firmware file is
+ valid. */
+ crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
+ memcpy(&tmp, &firmware[56], 4);
+ crc32_check = htonl(tmp);
+ if (crc32_csum != crc32_check) {
+ printk("%s: crc32 check of DSP code failed (calculated "
+ "0x%08x != 0x%08x in file), file invalid.\n",
+ __FUNCTION__, crc32_csum, crc32_check);
+ return -1;
+ }
+ memcpy(idstring, &firmware[36], 20);
+ idstring[20] = '\0';
+ printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
firmware_size_nl = htonl(firmware_size);
memcpy(b0, &firmware_size_nl, 4);
- firmware_csum_nl = htonl(firmware_csum);
- memcpy(&b0[6], &firmware_csum_nl, 4);
+ firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0;
+ firmware_csum_ns = htons(firmware_csum);
+ memcpy(&b0[6], &firmware_csum_ns, 2);
result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
@@ -1125,18 +1193,25 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
static int ttusb_dec_init_stb(struct ttusb_dec *dec)
{
- u8 c[COMMAND_PACKET_SIZE];
- int c_length;
int result;
+ unsigned int mode, product, version;
dprintk("%s\n", __FUNCTION__);
- result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+ result = ttusb_dec_get_stb_state(dec, &mode, &product, &version);
if (!result) {
- if (c_length != 0x0c || (c_length == 0x0c && c[9] != 0x63))
+ if (!mode) {
+ if (version == 0xABCDEFAB)
+ printk(KERN_INFO "ttusb_dec: no version "
+ "info in Firmware\n");
+ else
+ printk(KERN_INFO "ttusb_dec: Firmware "
+ "%x.%02x%c%c\n",
+ version >> 24, (version >> 16) & 0xff,
+ (version >> 8) & 0xff, version & 0xff);
return ttusb_dec_boot_dsp(dec);
- else
+ } else
return 0;
}
else
@@ -1572,13 +1647,13 @@ static int ttusb_dec_probe(struct usb_interface *intf,
case 0x1006:
dec->model = TTUSB_DEC3000S;
dec->model_name = "DEC3000-s";
- dec->firmware_name = "dvb-ttusb-dec-3000s-2.15a.fw";
+ dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
break;
case 0x1008:
dec->model = TTUSB_DEC2000T;
dec->model_name = "DEC2000-t";
- dec->firmware_name = "dvb-ttusb-dec-2000t-2.15a.fw";
+ dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
break;
}