Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7635acd2 authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds
Browse files

[PATCH] dvb: flexcop: fix USB transfer handling



- driver receives many null TS packets (pid=0x1fff).  They occupy the
  limited USB bandwidth and this leads to loss of video packets.  Enabling the
  null packet filter fixes this.

- packets that flexcop sends to USB have a 2 byte header that has to be
  removed.

- sometimes a TS packet is split between different urbs.  These parts have
  to be combined in a temporary buffer.

Signed-off-by: default avatarVadim Catana <skystar@moldova.cc>
Signed-off-by: default avatarPatrick Boettcher <pb@linuxtv.org>
Signed-off-by: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2add87a9
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
	} else if (fc->feedcount == onoff && !onoff) {
		if (!fc->pid_filtering) {
			deb_ts("disabling full TS transfer\n");
			flexcop_pid_group_filter(fc, 0x1fe0,0);
			flexcop_pid_group_filter(fc, 0, 0x1fe0);
			flexcop_pid_group_filter_ctrl(fc,0);
		}

@@ -175,7 +175,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
		flexcop_pid_group_filter(fc, 0,0);
		flexcop_pid_group_filter_ctrl(fc,1);
	} else if (fc->pid_filtering && fc->feedcount <= max_pid_filter) {
		flexcop_pid_group_filter(fc, 0x1fe0,0);
		flexcop_pid_group_filter(fc, 0,0x1fe0);
		flexcop_pid_group_filter_ctrl(fc,0);
	}

@@ -189,10 +189,13 @@ void flexcop_hw_filter_init(struct flexcop_device *fc)
	for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
		flexcop_pid_control(fc,i,0x1fff,0);

	flexcop_pid_group_filter(fc, 0x1fe0,0);
	flexcop_pid_group_filter(fc, 0, 0x1fe0);
	flexcop_pid_group_filter_ctrl(fc,0);

	v = fc->read_ibi_reg(fc,pid_filter_308);
	v.pid_filter_308.EMM_filter_4 = 1;
	v.pid_filter_308.EMM_filter_6 = 0;
	fc->write_ibi_reg(fc,pid_filter_308,v);

	flexcop_null_filter_ctrl(fc, 1);
}
+46 −1
Original line number Diff line number Diff line
@@ -282,6 +282,51 @@ static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_
		return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
}

static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
{
	u8 *b;
	int l;

	deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length);

	if (fc_usb->tmp_buffer_length > 0) {
		memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length);
		fc_usb->tmp_buffer_length += buffer_length;
		b = fc_usb->tmp_buffer;
		l = fc_usb->tmp_buffer_length;
	} else {
		b=buffer;
		l=buffer_length;
	}

	while (l >= 190) {
		if (*b == 0xff)
			switch (*(b+1) & 0x03) {
				case 0x01: /* media packet */
					if ( *(b+2) == 0x47 )
						flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1);
					else
						deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) );

					b += 190;
					l -= 190;
				break;
				default:
					deb_ts("wrong packet type\n");
					l = 0;
				break;
			}
		else {
			deb_ts("wrong header\n");
			l = 0;
		}
	}

	if (l>0)
		memcpy(fc_usb->tmp_buffer, b, l);
	fc_usb->tmp_buffer_length = l;
}

static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
{
	struct flexcop_usb *fc_usb = urb->context;
@@ -297,7 +342,7 @@ static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
			if (urb->iso_frame_desc[i].actual_length > 0) {
				deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length);

				flexcop_pass_dmx_data(fc_usb->fc_dev,
				flexcop_usb_process_frame(fc_usb,
					urb->transfer_buffer + urb->iso_frame_desc[i].offset,
					urb->iso_frame_desc[i].actual_length);
		}
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ struct flexcop_usb {
	struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];

	struct flexcop_device *fc_dev;

	u8 tmp_buffer[1023+190];
	int tmp_buffer_length;
};

#if 0