mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
make copying to/from CA device more robust, add TDT callback
This commit is contained in:
70
lib/src/ca.c
70
lib/src/ca.c
@@ -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
133
lib/src/dvb_filter.h
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user