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

Commit f894165c authored by Ralph Metzler's avatar Ralph Metzler Committed by Mauro Carvalho Chehab
Browse files

media: dvb_ca_en50221: Add block read/write functions



Some lower level drivers may work better when sending blocks of data
instead byte per byte. For this we need new function pointers in the
dvb_ca_en50221 protocol structure (read_data, write_data) and the protocol
needs to execute them, if they are defined.
Block data transmission is done in all states except LINKINIT.

Original code change by Ralph Metzler, modified by Jasmin Jessich and
Daniel Scheller to match Kernel code style.

Signed-off-by: default avatarRalph Metzler <rjkm@metzlerbros.de>
Signed-off-by: default avatarDaniel Scheller <d.scheller@gmx.net>
Signed-off-by: default avatarJasmin Jessich <jasmin@anw.at>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 5dbddc99
Loading
Loading
Loading
Loading
+85 −52
Original line number Diff line number Diff line
@@ -645,14 +645,31 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
		}
		buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);

		if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
		if (buf_free < (ca->slot_info[slot].link_buf_size +
				DVB_RINGBUFFER_PKTHDRSIZE)) {
			status = -EAGAIN;
			goto exit;
		}
	}

	if (ca->pub->read_data &&
	    (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT)) {
		if (ebuf == NULL)
			status = ca->pub->read_data(ca->pub, slot, buf,
						    sizeof(buf));
		else
			status = ca->pub->read_data(ca->pub, slot, buf, ecount);
		if (status < 0)
			return status;
		bytes_read =  status;
		if (status == 0)
			goto exit;
	} else {

		/* check if there is data available */
	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
		status = ca->pub->read_cam_control(ca->pub, slot,
						   CTRLIF_STATUS);
		if (status < 0)
			goto exit;
		if (!(status & STATUSREG_DA)) {
			/* no data */
@@ -661,10 +678,14 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
		}

		/* read the amount of data */
	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
		status = ca->pub->read_cam_control(ca->pub, slot,
						   CTRLIF_SIZE_HIGH);
		if (status < 0)
			goto exit;
		bytes_read = status << 8;
	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
		status = ca->pub->read_cam_control(ca->pub, slot,
						   CTRLIF_SIZE_LOW);
		if (status < 0)
			goto exit;
		bytes_read |= status;

@@ -674,14 +695,16 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
				pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
				       ca->dvbdev->adapter->num, bytes_read,
				       ca->slot_info[slot].link_buf_size);
			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
				ca->slot_info[slot].slot_state =
						     DVB_CA_SLOTSTATE_LINKINIT;
				status = -EIO;
				goto exit;
			}
			if (bytes_read < 2) {
				pr_err("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
				       ca->dvbdev->adapter->num);
			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
				ca->slot_info[slot].slot_state =
						     DVB_CA_SLOTSTATE_LINKINIT;
				status = -EIO;
				goto exit;
			}
@@ -697,7 +720,9 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
		/* fill the buffer */
		for (i = 0; i < bytes_read; i++) {
			/* read byte and check */
		if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0)
			status = ca->pub->read_cam_control(ca->pub, slot,
							   CTRLIF_DATA);
			if (status < 0)
				goto exit;

			/* OK, store it in the buffer */
@@ -705,13 +730,17 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
		}

		/* check for read error (RE should now be 0) */
	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
		status = ca->pub->read_cam_control(ca->pub, slot,
						   CTRLIF_STATUS);
		if (status < 0)
			goto exit;
		if (status & STATUSREG_RE) {
		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
			ca->slot_info[slot].slot_state =
						     DVB_CA_SLOTSTATE_LINKINIT;
			status = -EIO;
			goto exit;
		}
	}

	/* OK, add it to the receive buffer, or copy into external buffer if supplied */
	if (ebuf == NULL) {
@@ -763,6 +792,10 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
	if (bytes_write > ca->slot_info[slot].link_buf_size)
		return -EINVAL;

	if (ca->pub->write_data &&
	    (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT))
		return ca->pub->write_data(ca->pub, slot, buf, bytes_write);

	/* it is possible we are dealing with a single buffer implementation,
	   thus if there is data available for read or if there is even a read
	   already in progress, we do nothing but awake the kernel thread to
+7 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@
 * @write_attribute_mem: function for writing attribute memory on the CAM
 * @read_cam_control:	function for reading the control interface on the CAM
 * @write_cam_control:	function for reading the control interface on the CAM
 * @read_data:		function for reading data (block mode)
 * @write_data:		function for writing data (block mode)
 * @slot_reset:		function to reset the CAM slot
 * @slot_shutdown:	function to shutdown a CAM slot
 * @slot_ts_enable:	function to enable the Transport Stream on a CAM slot
@@ -66,6 +68,11 @@ struct dvb_ca_en50221 {
	int (*write_cam_control)(struct dvb_ca_en50221 *ca,
				 int slot, u8 address, u8 value);

	int (*read_data)(struct dvb_ca_en50221 *ca,
				int slot, u8 *ebuf, int ecount);
	int (*write_data)(struct dvb_ca_en50221 *ca,
				int slot, u8 *ebuf, int ecount);

	int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot);
	int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot);
	int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot);