[linux-dvb] Patch for broken dst_ca

Sigmund Augdal Helberg sigmund at snap.tv
Wed Apr 12 15:44:07 CEST 2006


On Wed, 2006-04-12 at 22:56 +1000, linuxtv at zacglen.com.au wrote:
> 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).
I ack that current code isn't correct, but this patch needs a little
revition, but it's nearly there.
> 
> Ok, so apparently nobody has this problem except myself.
Indeed, of all the channels I've ever tested no one was ever near to
getting a ca_pmt >127 bytes. This said, such a case isn't impossible,
and the dst can handle up to 255 bytes.
> Ok, so I have already posted about this but it has fallen on deaf ears.
No, it hasn't fallen of deaf ears, but as no patch for it was posted no
one has yet to step up to fix the problem. (we are buzy people here)
> Ok, so I also vote Abraham off as the weakest link.
You can say whatever you like about Mr Abraham, but there are _no_
documentation for the dst whatsoever except the knowledge of this
particular person. Voting him out (Hey we are a open source community
here, not a reality show!) will leave wild guesses (like this patch
here) as the only possible choice for impoving anything with these
cards. You are free to not like this situation, but mr Abraham is not
the one to yell at. Try taking on Twinhan in stread.

Specific comments about the patch to follow:
> 
> 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
> +		 */
Incorrect, this is a hardware specific commands along the lines found in
all hardware communications in dst.c and dst_ca.c

>  		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? */
It is just a single byte.
>  		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);
This change is the only actually needed change in the patch.
>  	}
>  	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);
>  		}
>  	}
These are all well and good, but since the dst can't cope with sizes
larger than 255 bytes checking the return value for >127 should be
enough to handle the two byte case.
> @@ -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 */
Every command sent to the dst ends with such a checksum. Try to keep
patches that fix things as small as possible to avoid confusion.
> +	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;
in addition length > (255 - 3 (tag) - lensize + 7) should be checked
for, this is because of the reformating of the capmt and the dsts limit
on 255 bytes for it's communication units.
> +	debug_string(&p_ca_message->msg[3+lensize], length, 0); /*	length is excluding tag & length	*/
this line will read out-of-buffer memory if length ==
sizeof(p_ca_message->message) or up to 3+lensize bytes shorter. (yes I
know the line you removed had this issue as well.
>  
>  	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");
One more needless change. The pure cosmetics can go in a separate patch.
>  			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;
> 
Finally, please provide a Signed-off-by line in your patch submission.
And don't mingle patch description with questions as the description
will stay in changelogs forever. Please read the patch submission
guidelines for details on these points.

Regards

Sigmund

> 
> _______________________________________________
> linux-dvb mailing list
> linux-dvb at linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb




More information about the linux-dvb mailing list