[linux-dvb] Patch for broken dst_ca
linuxtv at zacglen.com.au
linuxtv at zacglen.com.au
Wed Apr 12 14:56:05 CEST 2006
Here is a patch for dst_ca.c which addresses the issue of
messages over 128 bytes long (when asn1 length is more than 1 byte).
Ok, so apparently nobody has this problem except myself.
Ok, so I have already posted about this but it has fallen on deaf ears.
Ok, so I also vote Abraham off as the weakest link.
Here is it (btw it also replicates some existing patches):
===============================================================================
--- kernel-2.6.14/linux-2.6.14/drivers/media/dvb/bt8xx/dst_ca.c.mxy 2005-10-28 10:02:08.000000000 +1000
+++ kernel-2.6.14/linux-2.6.14/drivers/media/dvb/bt8xx/dst_ca.c 2006-04-09 11:41:33.000000000 +1000
@@ -275,7 +275,7 @@
return 0;
}
-static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
+static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, int lensize, struct ca_msg *hw_buffer, u32 length)
{
if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
@@ -286,17 +286,26 @@
return -1;
}
hw_buffer->msg[0] = (length & 0xff) + 7;
+ /*
+ * This is probably a resource, as per EN50221 8.2.2 Table 15.
+ * type=1 2 bits
+ * class=3 (CA) 14 bits
+ * type=0 10 bits
+ * version=3 6 bits
+ */
hw_buffer->msg[1] = 0x40;
hw_buffer->msg[2] = 0x03;
hw_buffer->msg[3] = 0x00;
hw_buffer->msg[4] = 0x03;
+
+ /* But this is odd ... not asn1, and lsb,msb? */
hw_buffer->msg[5] = length & 0xff;
hw_buffer->msg[6] = 0x00;
/*
* Need to compute length for EN50221 section 8.3.2, for the time being
* assuming 8.3.2 is not applicable
*/
- memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
+ memcpy(&hw_buffer->msg[7], &p_ca_message->msg[3+lensize], length);
}
return 0;
}
@@ -315,11 +324,12 @@
return 0;
}
-u32 asn_1_decode(u8 *asn_1_array)
+u32 asn_1_decode(u8 *asn_1_array, int *plensize)
{
u8 length_field = 0, word_count = 0, count = 0;
u32 length = 0;
+ *plensize = 1;
length_field = asn_1_array[0];
dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
if (length_field < 0x80) {
@@ -327,8 +337,10 @@
dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
} else {
word_count = length_field & 0x7f;
+ *plensize += word_count;
for (count = 0; count < word_count; count++) {
- length = (length | asn_1_array[count + 1]) << 8;
+ length = length << 8;
+ length += asn_1_array[count + 1];
dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
}
}
@@ -350,14 +362,17 @@
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
{
u32 length = 0;
- u8 tag_length = 8;
+ u8 tag_length = 7+1; /* 1 for checksum */
+ int lensize = 0;
- length = asn_1_decode(&p_ca_message->msg[3]);
+ length = asn_1_decode(&p_ca_message->msg[3], &lensize);
dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
- debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */
+ if (length > sizeof(p_ca_message->msg))
+ return -1;
+ debug_string(&p_ca_message->msg[3+lensize], length, 0); /* length is excluding tag & length */
memset(hw_buffer->msg, '\0', length);
- handle_dst_tag(state, p_ca_message, hw_buffer, length);
+ handle_dst_tag(state, p_ca_message, lensize, hw_buffer, length);
put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */
@@ -430,7 +445,7 @@
switch (command) {
case CA_PMT:
- dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+ dprintk(verbose, DST_CA_DEBUG, 1, "Command = CA_PMT");
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
return -1;
More information about the linux-dvb
mailing list