make copying to/from CA device more robust, add TDT callback

This commit is contained in:
rjkm
2024-03-29 14:04:33 +01:00
parent 62b0b57c5d
commit 4197d9a59e
4 changed files with 198 additions and 244 deletions

View File

@@ -31,6 +31,23 @@
#define MMI_STATE_ENQ 2
#define MMI_STATE_MENU 3
void dump(FILE *fp, uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%02x ", b[i]);
else
fprintf(fp, " ");
fprintf(fp, " | ");
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%c", (b[i] > 31 && b[i] < 127) ? b[i] : '.');
fprintf(fp, "\n");
}
}
int set_nonblock(int fd)
{
@@ -166,24 +183,23 @@ static int handle_pmt(struct dvbca *ca, uint8_t *buf, int size)
#endif
#if 0
static void handle_tdt(struct dddvb_ca *ca)
{
struct section *section;
struct dvb_tdt_section *tdt;
uint8_t sec[4096];
uint8_t *sec=ca->dvbf_tdt.buf;
time_t dvb_time;
int len;
int len=ca->dvbf_tdt.len;
if (sec[0] != 0x70)
return;
dbgprintf(DEBUG_CA, "got tdt\n");
//dump(stderr, sec,len);
if (ca->stdcam == NULL)
return;
if (ca->stdcam->dvbtime == NULL)
return;
len = getsec(ca->input, 0x14, 0, 0x70, sec);
if (len < 0)
return;
dbgprintf(DEBUG_CA, "got tdt\n");
section = section_codec(sec, len);
if (section == NULL)
return;
@@ -196,7 +212,7 @@ static void handle_tdt(struct dddvb_ca *ca)
if (ca->stdcam->dvbtime)
ca->stdcam->dvbtime(ca->stdcam, dvb_time);
}
#endif
static int handle_pmts(struct dddvb_ca *ca)
{
@@ -253,24 +269,6 @@ static int handle_pmts(struct dddvb_ca *ca)
return 0;
}
void dump(FILE *fp, uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%02x ", b[i]);
else
fprintf(fp, " ");
fprintf(fp, " | ");
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%c", (b[i] > 31 && b[i] < 127) ? b[i] : '.');
fprintf(fp, "\n");
}
}
static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
{
int listmgmt = CA_LIST_MANAGEMENT_ONLY;
@@ -303,6 +301,8 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
dbgprintf(DEBUG_CA, "section_ext_decode failed\n");;
continue;
}
//dump(stderr, (uint8_t *) section, len);
//dump(stderr, (uint8_t *) section_ext, len);
pmt = mpeg_pmt_section_codec(section_ext);
//pmt = (struct mpeg_pmt_section *) section_ext;
if (!pmt) {
@@ -310,7 +310,7 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
continue;
}
dbgprintf(DEBUG_CA, "PMT = %p section=%p\n", pmt, section);
//dbgprintf(DEBUG_CA, "PMT = %p section=%p\n", pmt, section);
ca->ca_pmt_version[i] = section_ext->version_number;
if (ca->sentpmt) {
@@ -334,7 +334,7 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
dbgprintf(DEBUG_CA, "Failed to format PMT\n");
return -1;
}
//dump(capmt, size);
//dump(stderr, capmt, size);
dbgprintf(DEBUG_CA, "set ca_pmt\n");
if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
dbgprintf(DEBUG_CA, "Failed to send PMT\n");
@@ -697,6 +697,7 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
pthread_create(&ca->poll_pt, NULL, (void *) ci_poll, ca);
pthread_create(&ca->pt, NULL, (void *) handle_ci, ca);
dvbf_init_pid(&ca->dvbf_tdt, 0x14);
sprintf(fname, "/dev/dvb/adapter%d/ci%d", a, f);
ca->ci_wfd = open(fname, O_WRONLY);
@@ -708,7 +709,16 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len)
{
struct dddvb_ca *ca = &dd->dvbca[nr];
uint32_t i;
if (len%188)
return -EINVAL;
for (i = 0; i < len; i+=188) {
if (proc_pidf(&ca->dvbf_tdt, buf+i)>0)
handle_tdt(ca);
}
return write(ca->ci_wfd, buf, len);
}

133
lib/src/dvb_filter.h Normal file
View File

@@ -0,0 +1,133 @@
static inline uint16_t seclen(const uint8_t *buf)
{
return 3+((buf[1]&0x0f)<<8)+buf[2];
}
static inline uint16_t tspid(const uint8_t *buf)
{
return ((buf[1]&0x1f)<<8)+buf[2];
}
static inline int tspayload(const uint8_t *tsp)
{
if (!(tsp[3] & 0x10))
return 0;
if (tsp[3] & 0x20)
return (tsp[4] > 183) ? 0 : (183 - tsp[4]);
return 184;
}
static inline int tspaystart(const uint8_t *tsp)
{
if (!(tsp[3]&0x10))
return 188;
if (tsp[3]&0x20)
return (tsp[4] >= 184) ? 188 : tsp[4]+5;
return 4;
}
struct dvbf_pid {
uint16_t pid;
uint8_t cc;
uint16_t bufp;
uint16_t len;
uint8_t buf[4096];
int (*cb) (struct dvbf_pid *);
void *cbd;
};
static inline void pidf_reset(struct dvbf_pid *pidf)
{
pidf->bufp = pidf->len = 0;
}
static inline void dvbf_init_pid(struct dvbf_pid *pidf, uint16_t pid)
{
pidf->pid = pid;
pidf->cc = 0xff;
pidf_reset(pidf);
}
static inline void write_secbuf(struct dvbf_pid *p, uint8_t *tsp, int n)
{
memcpy(p->buf+p->bufp, tsp, n);
p->bufp += n;
}
static inline int validcc(struct dvbf_pid *p, uint8_t *tsp)
{
uint8_t newcc;
int valid;
newcc = tsp[3] & 0x0f;
if (p->cc == 0xff)
valid=1;
else
valid = (((p->cc + 1) & 0x0f) == newcc) ? 1 : 0;
p->cc = newcc;
if (!valid)
pidf_reset(p);
return valid;
}
static int proc_pidf(struct dvbf_pid *p, uint8_t *tsp)
{
int pusoff, todo, off;
if (tspid(tsp) != p->pid)
return 0;
if (!(tsp[3] & 0x10)) //no payload
return 0;
todo = (tsp[3] & 0x20) ? // AF?
((tsp[4] > 183) ? 0 : (183 - tsp[4])) :
184;
if (!todo)
return 0;
off = 188 - todo;
pusoff = (tsp[1] & 0x40) ? tsp[off++] : todo;
if (pusoff + off > 188)
goto error;
if (validcc(p, tsp) && pusoff && p->bufp) {
int rlen = pusoff;
if (p->len) {
if (p->bufp + rlen > p->len)
rlen = p->len - p->bufp;
} else
if (p->bufp + rlen > 4096)
rlen = 4096 - p->bufp;
write_secbuf(p, tsp + off, rlen);
if (!p->len && p->bufp >= 3 && (p->len = seclen(p->buf)) > 4096)
pidf_reset(p);
else {
if (p->cb)
p->cb(p);
else
return 1;
}
}
off += pusoff;
while ((todo = 188 - off) > 0 && tsp[off] != 0xff) {
pidf_reset(p);
if (todo < 3 || (p->len = seclen(tsp+off)) > todo) {
if (p->len > 4096)
goto error;
write_secbuf(p, tsp+off, todo);
off+=todo;
} else {
write_secbuf(p, tsp+off, p->len);
off+=p->len;
if (p->cb)
p->cb(p);
else
return 2;
}
}
return 0;
error:
pidf_reset(p);
return -1;
}