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; _______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb