summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authorAlex Woods <devnull@localhost>2004-01-04 22:07:57 +0000
committerAlex Woods <devnull@localhost>2004-01-04 22:07:57 +0000
commit539fe957e343be686be416ccf137396bca953e07 (patch)
tree1c485d88b18197077156cb4388b13c59b23bf3a7 /linux/drivers/media/dvb
parenteaef046bcb06617776887ce5876c3bc4ffb60f2d (diff)
downloadmediapointer-dvb-s2-539fe957e343be686be416ccf137396bca953e07.tar.gz
mediapointer-dvb-s2-539fe957e343be686be416ccf137396bca953e07.tar.bz2
Apply Hans-Frieder Vogt's patch for calculating firmware CRCs.
Update ttusb-dec docs accordingly. Add him to contributors file and correct a typo.
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c113
1 files changed, 94 insertions, 19 deletions
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;
}