diff --git a/Makefile b/Makefile index 941d596..62cd3b6 100644 --- a/Makefile +++ b/Makefile @@ -12,11 +12,17 @@ MAKE=gmake DEFS=-D_REENTRANT -D_TS_ERRNO -DHMT_PROTECT # -DWITH_MPATROL -SRCS= epg.c \ +SRCS= descriptor.c \ + epg.c \ file.c \ main.c \ util.c +HDRS= descriptor.h \ + epg.h \ + lint.h \ + util.h + OBJS= $(SRCS:.c=.o) CC=gcc #CC=mipsel-linux-gcc @@ -61,5 +67,5 @@ tags: @echo " $<" @$(CC) $(CFLAGS) ${WARN} ${DEFS} ${INCS} -c $< -o $@ -${OBJS}: lint.h +${OBJS}: ${HDRS} diff --git a/descriptor.c b/descriptor.c new file mode 100644 index 0000000..07a636b --- /dev/null +++ b/descriptor.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + +void +read_descriptor(struct epg *epg, struct descriptor *d) +{ + switch (d->tag) + { + case 77: + memcpy(d->content.d77.language, epg->bin + epg->offset, 3); + 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; + + default: + epg->offset += d->len; + 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: + free(d->content.d77.name); + free(d->content.d77.text); + break; + default: + 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: + DUMPNSTR(d, content.d77.language, 3); + 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; + + default: + break; + } +} + diff --git a/descriptor.h b/descriptor.h new file mode 100644 index 0000000..28da390 --- /dev/null +++ b/descriptor.h @@ -0,0 +1,23 @@ +#define DS_LINKAGE 74 +#define DS_SHORT_EVENT 77 +#define DS_COMPONENT 80 +#define DS_CONTENT 84 +#define DS_PRIVATE_DATA_SPECIFIER 95 +#define DS_CONTENT_IDENTIFIER 118 +#define DS_FTA_CONTENT_MGMT 126 +#define DS_USER_DEFINED 137 + +struct descriptor { + unsigned int tag:8; + unsigned int len:8; + union { + struct { + char language[3]; + unsigned int namelen:8; + unsigned int textlen:8; + char *name; + char *text; + } d77; + } content; +}; + diff --git a/epg.c b/epg.c index 9759dea..3e0aa29 100644 --- a/epg.c +++ b/epg.c @@ -9,18 +9,16 @@ #include "lint.h" -#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8)) - -struct section_header * -read_section_header(struct epg *epg) +struct section * +read_section(struct epg *epg) { - static struct section_header h; + static struct section h; if (epg->binsize - epg->offset < sizeof(h)) return NULL; memcpy(&h, epg->bin + epg->offset, sizeof(h)); - if (memcmp(h.magic, SECTION_HEADER_MAGIC, sizeof(h.magic))) + if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic))) { printf("Section header magic mismatch.\n"); return NULL; @@ -38,6 +36,27 @@ read_section_header(struct epg *epg) return &h; } +void +dump_section(struct section *h) +{ + printf("Section header:\n"); + DUMPINT(h, total_length); + DUMPINT(h, table_id); + DUMPINT(h, u1.u.syntax_indicator); + DUMPINT(h, u1.u.reserved); + DUMPINT(h, u1.u.length); + DUMPINT(h, service_id); + DUMPINT(h, reserved2); + DUMPINT(h, version_number); + DUMPINT(h, current_next_indicator); + DUMPINT(h, section_number); + DUMPINT(h, last_section_number); + DUMPINT(h, transport_stream_id); + DUMPINT(h, original_network_id); + DUMPINT(h, segment_last_section_number); + DUMPINT(h, last_table_id); +} + struct data * read_data(struct epg *epg) { @@ -57,58 +76,6 @@ read_data(struct epg *epg) return &d; } -struct descriptor_header * -read_descriptor_header(struct epg *epg) -{ - static struct descriptor_header d; - - if (epg->binsize - epg->offset < sizeof(d)) - return NULL; - - memcpy(&d, epg->bin + epg->offset, sizeof(d)); - - epg->offset += sizeof(d); - - return &d; -} - -#define DUMPINT(ss,xx) printf(" %30s: %d\n", #xx, ss->xx) -#define DUMPSTR(ss,xx) printf(" %30s: %s\n", #xx, ss->xx) -#define DUMPHEX(ss,xx) printf(" %30s: %s\n", #xx, \ - hexstr(ss->xx, sizeof(ss->xx))) - -char * -ctime_nl(time_t *tm) -{ - static char buf[26]; - - strcpy(buf, ctime(tm)); - *strchr(buf, '\n') = '\0'; - - return buf; -} - -void -dump_section_header(struct section_header *h) -{ - printf("Section header:\n"); - DUMPINT(h, total_length); - DUMPINT(h, table_id); - DUMPINT(h, u1.u.syntax_indicator); - DUMPINT(h, u1.u.reserved); - DUMPINT(h, u1.u.length); - DUMPINT(h, service_id); - DUMPINT(h, reserved2); - DUMPINT(h, version_number); - DUMPINT(h, current_next_indicator); - DUMPINT(h, section_number); - DUMPINT(h, last_section_number); - DUMPINT(h, transport_stream_id); - DUMPINT(h, original_network_id); - DUMPINT(h, segment_last_section_number); - DUMPINT(h, last_table_id); -} - void dump_data(struct data *d) { @@ -131,30 +98,3 @@ dump_data(struct data *d) DUMPINT(d, u1.u.descriptors_loop_length); } -char * -descriptor_name(struct descriptor_header *d) -{ - switch (d->tag) - { - case 77: return "short event"; - case 80: return "component"; - case 137: return "user defined"; - case 118: return "content identifier"; - case 74: return "linkage"; - case 84: return "content"; - case 95: return "private data specifier"; - case 126: return "FTA content management"; - default: return "Unknown"; - } - return "Unknown"; -} - -void -dump_descriptor_header(struct descriptor_header *d) -{ - printf("Descriptor header:\n"); - printf(" %30s: %#x [%d] (%s)\n", "descriptor", d->tag, d->tag, - descriptor_name(d)); - DUMPINT(d, len); -} - diff --git a/epg.h b/epg.h index 75d4349..aa9438e 100644 --- a/epg.h +++ b/epg.h @@ -9,10 +9,10 @@ struct epg { uint32_t binsize; }; -#define SECTION_HEADER_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01" +#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01" #pragma pack(1) -struct section_header { +struct section { char magic[14]; unsigned int total_length:16; unsigned int magic2:32; @@ -37,6 +37,7 @@ struct section_header { unsigned int last_table_id:8; }; +#pragma pack(1) struct data { unsigned int event_id:16; unsigned int start_date:16; @@ -56,8 +57,3 @@ struct data { } u1; }; -struct descriptor_header { - unsigned int tag:8; - unsigned int len:8; -}; - diff --git a/lint.h b/lint.h index 0aba05d..c15097b 100644 --- a/lint.h +++ b/lint.h @@ -1,8 +1,7 @@ #include "epg.h" - -/* Works for modern dates, 1970 - 2038 */ -#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400) +#include "descriptor.h" +#include "util.h" extern int debug; extern const char *version; @@ -11,17 +10,21 @@ extern unsigned long sysopts; inline uint16_t read_uint16(uint8_t *, int); inline uint32_t read_uint32(uint8_t *, int); void hexdump(uint8_t *, uint32_t, uint32_t); -void hexstr(uint8_t *, uint32_t); +char *hexstr(uint8_t *, uint32_t); +char *ctime_nl(time_t *); +char *read_string_len(uint8_t *, uint32_t); struct epg *open_file(char *); void close_file(struct epg *); -struct section_header *read_section_header(struct epg *); -void dump_section_header(struct section_header *); +struct section *read_section(struct epg *); +void dump_section(struct section *); struct data *read_data(struct epg *); void dump_data(struct data *); -struct descriptor_header *read_descriptor_header(struct epg *); -void dump_descriptor_header(struct descriptor_header *); +struct descriptor *read_descriptor_header(struct epg *); +void read_descriptor(struct epg *, struct descriptor *); +void skip_descriptor(struct epg *, struct descriptor *); +void dump_descriptor(struct descriptor *, int); diff --git a/main.c b/main.c index 02fc8db..f15f81e 100644 --- a/main.c +++ b/main.c @@ -36,8 +36,7 @@ syntax() int main(int argc, char **argv) { - struct section_header *h; - struct data *d; + struct section *h; struct epg *epg; if (!(epg = open_file("../epg.dat"))) @@ -45,36 +44,44 @@ main(int argc, char **argv) while (epg->offset < epg->binsize) { - uint32_t end; + uint32_t send; - if (!(h = read_section_header(epg))) + if (!(h = read_section(epg))) break; - dump_section_header(h); + //dump_section(h); - end = epg->offset - 11 + h->u1.u.length - 4; + send = epg->offset - 11 + h->u1.u.length - 4; - while (epg->offset < end) + while (epg->offset < send) { + struct data *d; uint32_t dend; if (!(d = read_data(epg))) break; - dump_data(d); + //dump_data(d); dend = epg->offset + d->u1.u.descriptors_loop_length; while (epg->offset < dend) { - struct descriptor_header *dh; + struct descriptor *ds; - dh = read_descriptor_header(epg); - dump_descriptor_header(dh); - - epg->offset += dh->len; + ds = read_descriptor_header(epg); + if (ds->tag == DS_SHORT_EVENT) + { + read_descriptor(epg, ds); + dump_descriptor(ds, 1); + } + else + { + dump_descriptor(ds, 0); + skip_descriptor(epg, ds); + } +printf("Offset: %d / %d\n", epg->offset, dend); } - //goto stop; } - /* Section CRC */ + /* Skip CRC */ epg->offset += 4; /* Skip padding bytes... */ diff --git a/util.c b/util.c index b5cc8d8..b512ca3 100644 --- a/util.c +++ b/util.c @@ -12,6 +12,26 @@ #include "lint.h" +char * +ctime_nl(time_t *tm) +{ + static char buf[26]; + + strcpy(buf, ctime(tm)); + *strchr(buf, '\n') = '\0'; + + return buf; +} + +inline char * +read_string_len(uint8_t *src, uint32_t len) +{ + char *s = malloc(len + 1); + memcpy(s, src, len); + s[len] = '\0'; + return s; +} + inline uint32_t read_uint32(uint8_t *p, int le) { @@ -77,9 +97,10 @@ hexdump(uint8_t *s, uint32_t len, uint32_t o) } } -void +char * hexstr(uint8_t *s, uint32_t len) { + static char buf[0x1000]; uint16_t off; if (!s) @@ -88,6 +109,7 @@ hexstr(uint8_t *s, uint32_t len) if (!len) len = strlen((char *)s); + memset(buf, '\0', sizeof(buf)); for (off = 0; off < len; off += 16) { uint32_t i; @@ -95,9 +117,10 @@ hexstr(uint8_t *s, uint32_t len) for (i = off; i - off < 16; i++) { if (i < len) - printf("%02x", s[i] & 0xff); + sprintf(buf + i * 3, "%02x ", s[i] & 0xff); } } + return buf; } void diff --git a/util.h b/util.h new file mode 100644 index 0000000..b5b7724 --- /dev/null +++ b/util.h @@ -0,0 +1,11 @@ + +/* Works for modern dates, 1970 - 2038 */ +#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400) + +#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8)) + +#define DUMPINT(ss,xx) printf(" %30s: %d\n", #xx, ss->xx) +#define DUMPSTR(ss,xx) printf(" %30s: %s\n", #xx, ss->xx) +#define DUMPNSTR(ss,xx,nn) printf(" %30s: %.*s\n", #xx, nn, ss->xx) +#define DUMPHEX(ss,xx,nn) printf(" %30s: %s\n", #xx, hexstr(ss->xx, nn)) +