1
0
Fork 0

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: Ralph Metzler <rjkm@metzlerbros.de>
Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Signed-off-by: Jasmin Jessich <jasmin@anw.at>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
hifive-unleashed-5.1
Ralph Metzler 2017-06-25 18:37:07 -03:00 committed by Mauro Carvalho Chehab
parent 5dbddc99ec
commit f894165cb5
2 changed files with 96 additions and 56 deletions

View File

@ -645,74 +645,103 @@ 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;
}
}
/* check if there is data available */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
if (!(status & STATUSREG_DA)) {
/* no data */
status = 0;
goto exit;
}
/* read the amount of data */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
goto exit;
bytes_read = status << 8;
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
goto exit;
bytes_read |= status;
/* check it will fit */
if (ebuf == NULL) {
if (bytes_read > ca->slot_info[slot].link_buf_size) {
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;
status = -EIO;
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;
}
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;
status = -EIO;
goto exit;
}
} else {
if (bytes_read > ecount) {
pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
ca->dvbdev->adapter->num);
/* check if there is data available */
status = ca->pub->read_cam_control(ca->pub, slot,
CTRLIF_STATUS);
if (status < 0)
goto exit;
if (!(status & STATUSREG_DA)) {
/* no data */
status = 0;
goto exit;
}
/* read the amount of data */
status = ca->pub->read_cam_control(ca->pub, slot,
CTRLIF_SIZE_HIGH);
if (status < 0)
goto exit;
bytes_read = status << 8;
status = ca->pub->read_cam_control(ca->pub, slot,
CTRLIF_SIZE_LOW);
if (status < 0)
goto exit;
bytes_read |= status;
/* check it will fit */
if (ebuf == NULL) {
if (bytes_read > ca->slot_info[slot].link_buf_size) {
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;
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;
status = -EIO;
goto exit;
}
} else {
if (bytes_read > ecount) {
pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
ca->dvbdev->adapter->num);
status = -EIO;
goto exit;
}
}
/* fill the buffer */
for (i = 0; i < bytes_read; i++) {
/* read byte and check */
status = ca->pub->read_cam_control(ca->pub, slot,
CTRLIF_DATA);
if (status < 0)
goto exit;
/* OK, store it in the buffer */
buf[i] = status;
}
/* check for read error (RE should now be 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;
status = -EIO;
goto exit;
}
}
/* 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)
goto exit;
/* OK, store it in the buffer */
buf[i] = status;
}
/* check for read error (RE should now be 0) */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
if (status & STATUSREG_RE) {
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) {
if (ca->slot_info[slot].rx_buffer.data == 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

View File

@ -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);