epg/descriptor.c

239 lines
5.6 KiB
C
Raw Normal View History

2011-06-02 11:14:43 +00:00
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <strings.h>
#include "lint.h"
struct descriptor *
read_descriptor_header(struct epg *epg)
{
static struct descriptor d;
if (epg->binsize - epg->offset < 2)
return NULL;
memcpy(&d, epg->bin + epg->offset, 2);
epg->offset += 2;
return &d;
}
2011-06-02 14:38:25 +00:00
static char *
string_to_end(struct epg *epg, struct descriptor *d, int sofar,
unsigned int *len)
{
int rest = d->len - sofar;
char *str;
*len = rest;
if (rest <= 0)
return NULL;;
str = (char *)malloc(rest + 1);
memcpy(str, epg->bin + epg->offset, rest);
str[rest] = '\0';
epg->offset += rest;
return str;
}
2011-06-02 11:14:43 +00:00
void
read_descriptor(struct epg *epg, struct descriptor *d)
{
switch (d->tag)
{
2011-06-02 14:38:25 +00:00
case DS_SHORT_EVENT:
memcpy(d->content.d77.lang, epg->bin + epg->offset, 3);
2011-06-02 11:14:43 +00:00
epg->offset += 3;
d->content.d77.namelen = epg->bin[epg->offset++];
d->content.d77.name = read_string_len(epg->bin + epg->offset,
d->content.d77.namelen);
epg->offset += d->content.d77.namelen;
d->content.d77.textlen = epg->bin[epg->offset++];
d->content.d77.text = read_string_len(epg->bin + epg->offset,
d->content.d77.textlen);
epg->offset += d->content.d77.textlen;
break;
2011-06-02 14:38:25 +00:00
case DS_COMPONENT:
memcpy(&d->content.d80, epg->bin + epg->offset, 6);
epg->offset += 6;
d->content.d80.text = string_to_end(epg, d, 6,
&d->content.d80.textlen);
break;
2011-06-02 15:21:56 +00:00
case DS_USER_DEFINED:
d->content.d137.textlen = epg->bin[epg->offset++];
d->content.d137.text = read_string_len(epg->bin + epg->offset,
d->content.d137.textlen);
epg->offset += d->content.d137.textlen;
memcpy(d->content.d137.lang, epg->bin + epg->offset, 3);
epg->offset += 3;
d->content.d137.warning = string_to_end(epg, d,
4 + d->content.d137.textlen,
&d->content.d137.warninglen);
break;
case DS_CONTENT_IDENTIFIER:
memcpy(&d->content.d118, epg->bin + epg->offset, 1);
epg->offset++;
d->content.d118.cridlen = d->content.d118.ref = 0;
switch (d->content.d118.location)
{
case 0:
d->content.d118.cridlen = epg->bin[epg->offset++];
d->content.d118.crid = read_string_len(
epg->bin + epg->offset, d->content.d118.cridlen);
epg->offset += d->content.d118.cridlen;
break;
case 1:
d->content.d118.ref =
_swap16((uint16_t)epg->bin[epg->offset]);
/* Not safe to use post increment in macro */
epg->offset++;
break;
default:
printf("Unknown CRID location - %d\n",
d->content.d118.location);
}
break;
2011-06-02 11:14:43 +00:00
default:
2011-06-02 15:25:00 +00:00
printf("Default descriptor: %d\n", d->tag);
case DS_LINKAGE:
case DS_CONTENT:
case DS_PRIVATE_DATA_SPECIFIER:
case DS_FTA_CONTENT_MGMT:
2011-06-02 15:21:56 +00:00
d->content.unknown.text = string_to_end(epg, d, 0,
&d->content.unknown.textlen);
2011-06-02 11:14:43 +00:00
break;
}
}
inline void
skip_descriptor(struct epg *epg, struct descriptor *d)
{
epg->offset += d->len;
}
void
free_descriptor(struct descriptor *d)
{
switch (d->tag)
{
case DS_SHORT_EVENT:
2011-06-02 14:38:25 +00:00
if (d->content.d77.name)
free(d->content.d77.name);
if (d->content.d77.text)
free(d->content.d77.text);
break;
case DS_COMPONENT:
if (d->content.d80.text)
free(d->content.d80.text);
2011-06-02 11:14:43 +00:00
break;
2011-06-02 15:21:56 +00:00
case DS_USER_DEFINED:
if (d->content.d137.text)
free(d->content.d137.text);
if (d->content.d137.warning)
free(d->content.d137.warning);
break;
case DS_CONTENT_IDENTIFIER:
if (d->content.d118.crid)
free(d->content.d118.crid);
break;
2011-06-02 11:14:43 +00:00
default:
2011-06-02 15:21:56 +00:00
if (d->content.unknown.text)
free(d->content.unknown.text);
2011-06-02 11:14:43 +00:00
break;
}
}
char *
descriptor_name(struct descriptor *d)
{
switch (d->tag)
{
case DS_LINKAGE: return "linkage";
case DS_SHORT_EVENT: return "short event";
case DS_COMPONENT: return "component";
case DS_CONTENT: return "content";
case DS_PRIVATE_DATA_SPECIFIER: return "private data spec.";
case DS_CONTENT_IDENTIFIER: return "content id";
case DS_FTA_CONTENT_MGMT: return "content mgmt";
case DS_USER_DEFINED: return "user defined";
default: return "Unknown";
}
return "Unknown";
}
void
dump_descriptor(struct descriptor *d, int content)
{
printf("Descriptor header:\n");
printf(" %30s: %#x [%d] (%s)\n", "descriptor", d->tag, d->tag,
descriptor_name(d));
DUMPINT(d, len);
if (!content)
return;
switch (d->tag)
{
case DS_SHORT_EVENT:
2011-06-02 14:38:25 +00:00
DUMPNSTR(d, content.d77.lang, 3);
2011-06-02 11:14:43 +00:00
DUMPINT(d, content.d77.namelen);
//DUMPNSTR(d, content.d77.name, d->content.d77.namelen);
DUMPHEX(d, content.d77.name, d->content.d77.namelen);
DUMPINT(d, content.d77.textlen);
//DUMPNSTR(d, content.d77.text, d->content.d77.textlen);
DUMPHEX(d, content.d77.text, d->content.d77.textlen);
break;
2011-06-02 14:38:25 +00:00
case DS_COMPONENT:
DUMPINT(d, content.d80.stream_content);
DUMPINT(d, content.d80.reserved);
DUMPINT(d, content.d80.type);
DUMPINT(d, content.d80.tag);
DUMPNSTR(d, content.d80.lang, 3);
if (d->content.d80.textlen)
DUMPHEX(d, content.d80.text, d->content.d80.textlen);
break;
2011-06-02 15:21:56 +00:00
case DS_USER_DEFINED:
DUMPINT(d, content.d137.textlen);
DUMPNSTR(d, content.d137.lang, 3);
DUMPHEX(d, content.d137.text, d->content.d137.textlen);
DUMPHEX(d, content.d137.warning, d->content.d137.warninglen);
break;
case DS_CONTENT_IDENTIFIER:
DUMPINT(d, content.d118.location);
DUMPINT(d, content.d118.type);
DUMPINT(d, content.d118.cridlen);
if (d->content.d118.cridlen)
DUMPHEX(d, content.d118.crid, d->content.d118.cridlen);
DUMPINT(d, content.d118.ref);
break;
2011-06-02 11:14:43 +00:00
default:
2011-06-02 15:21:56 +00:00
if (d->content.unknown.textlen)
DUMPHEX(d, content.unknown.text,
d->content.unknown.textlen);
2011-06-02 11:14:43 +00:00
break;
}
}