commit 9ebe37681bc083f857272d532a918c6157d33d4b Author: hummypkg Date: Wed Jun 1 23:34:35 2011 +0000 initial epg check-in diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..941d596 --- /dev/null +++ b/Makefile @@ -0,0 +1,65 @@ + +MAKE=gmake + +# Setting these makes sure that the subsequent include files know that +# we are going to be threaded so they should do whatever they need to +# support this. In particular, this makes the global variable 'errno' +# become thread safe by replacing it with a call to the internal function +# ___errno() on Solaris - and should do something similar on other operating +# systems. Solaris also supports _TS_ERRNO to enable thread-safe errno +# _REENTRANT is also required for the tempnam() function to be properly +# thread-safe. +DEFS=-D_REENTRANT -D_TS_ERRNO -DHMT_PROTECT +# -DWITH_MPATROL + +SRCS= epg.c \ + file.c \ + main.c \ + util.c + +OBJS= $(SRCS:.c=.o) +CC=gcc +#CC=mipsel-linux-gcc +PLATFORM=$(shell uname -s | cut -d- -f1) +PROCESSOR=$(shell uname -p) +CFLAGS=-g +INCS= +LIBS= +ifeq ($(PLATFORM),CYGWIN_NT) +CFLAGS=-g -mno-cygwin +endif +#ifeq ($(PLATFORM),Linux) +#CFLAGS=-static -g +#endif +#CFLAGS=-g -O3 -fno-strict-aliasing +#WARN=-pedantic -Wall -Wnested-externs -Wpointer-arith -Werror -Wno-unused +WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long + +all: tags epg + +epg: ${OBJS} + @echo "Linking..." + @-[ -f $@ ] && mv $@ $@~ || exit 0 + ${CC} -static-libgcc \ + ${WARN} \ + ${DEFS} \ + ${CFLAGS} -o $@ \ + ${OBJS} \ + ${LIBS} + @echo "Done..." + +clean: + @-touch core + rm -f epg epg~ *.exe core tags asm ${OBJS} ${AROBJS} + rm -f *.raw *.raw.sum *.lh5 + rm -rf epg-* + +tags: + @-ctags *.[ch] 2>> /dev/null + +.c.o: + @echo " $<" + @$(CC) $(CFLAGS) ${WARN} ${DEFS} ${INCS} -c $< -o $@ + +${OBJS}: lint.h + diff --git a/epg.c b/epg.c new file mode 100644 index 0000000..b189c23 --- /dev/null +++ b/epg.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lint.h" + +struct section_header * +read_section_header(struct epg *epg) +{ + static struct section_header 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))) + { + printf("Section header magic mismatch.\n"); + return NULL; + } + + epg->offset += sizeof(h); + + return &h; +} + +#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))) + +void +dump_section_header(struct section_header *h) +{ + printf("Section header:\n"); + DUMPINT(h, total_length); + DUMPINT(h, table_id); + DUMPINT(h, section_syntax_indicator); + DUMPINT(h, reserved); + DUMPINT(h, section_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) +{ + static struct data d; + + if (epg->binsize - epg->offset < sizeof(d)) + return NULL; + + memcpy(&d, epg->bin + epg->offset, sizeof(d)); + epg->offset += sizeof(d); + + return &d; +} + +void +dump_data(struct data *d) +{ + time_t tm; + + printf("Data:\n"); + DUMPINT(d, event_id); + DUMPINT(d, start_date); + + tm = MJD_TO_UNIX(d->start_date); + + printf(" %s", ctime(&tm)); + + DUMPINT(d, start_time); +// DUMPINT(d, duration); + DUMPINT(d, free_CA_mode); + DUMPINT(d, descriptors_loop_length); +} + diff --git a/epg.h b/epg.h new file mode 100644 index 0000000..596a23c --- /dev/null +++ b/epg.h @@ -0,0 +1,43 @@ + +#include + +struct epg { + char fname[MAXPATHLEN + 1]; + int fd; + uint8_t *bin; + uint32_t offset; + uint32_t binsize; +}; + +#define SECTION_HEADER_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01" + +#pragma pack(1) +struct section_header { + char magic[14]; + unsigned int total_length:16; + unsigned int magic2:32; + unsigned int table_id:8; + unsigned int section_syntax_indicator:1; + unsigned int reserved:3; + unsigned int section_length:12; + unsigned int service_id:16; + unsigned int reserved2:2; + unsigned int version_number:5; + unsigned int current_next_indicator:1; + unsigned int section_number:8; + unsigned int last_section_number:8; + unsigned int transport_stream_id:16; + unsigned int original_network_id:16; + unsigned int segment_last_section_number:8; + unsigned int last_table_id:8; +}; + +struct data { + unsigned int event_id:16; + unsigned int start_date:16; + unsigned int start_time:24; + char duration[3]; + unsigned int free_CA_mode:1; + unsigned int descriptors_loop_length:12; +}; + diff --git a/file.c b/file.c new file mode 100644 index 0000000..f36ff07 --- /dev/null +++ b/file.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lint.h" + +struct epg * +open_file(char *filename) +{ + struct epg *epg; + struct stat st; + + if (!(epg = malloc(sizeof(struct epg)))) + { + perror("malloc"); + return NULL; + } + + if (debug) + printf("Opening file '%s'\n", filename); + + strcpy(epg->fname, filename); + + if (stat(epg->fname, &st) == -1) + { + perror(epg->fname); + free(epg); + return NULL; + } + + epg->binsize = st.st_size; + + if (debug) + printf("Opening %s, %lu bytes.\n", epg->fname, + (unsigned long)epg->binsize); + + if ((epg->fd = open(epg->fname, O_RDONLY, 0)) == -1) + { + perror(epg->fname); + free(epg); + return NULL; + } + + epg->bin = (uint8_t *)mmap(NULL, epg->binsize, PROT_READ, + MAP_PRIVATE, epg->fd, 0); + if (epg->bin == MAP_FAILED) + { + perror("mmap"); + close(epg->fd); + free(epg); + return NULL; + } + + epg->offset = 0; + + return epg; +} + +void +close_file(struct epg *epg) +{ + if (debug) + printf("Closing file.\n"); + + munmap((void *)epg->bin, epg->binsize); + if (epg->fd > 0) + close(epg->fd); + epg->fd = -1; +} + diff --git a/lint.h b/lint.h new file mode 100644 index 0000000..d322b6e --- /dev/null +++ b/lint.h @@ -0,0 +1,24 @@ + +#include "epg.h" + +/* Works for modern dates, 1970 - 2038 */ +#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400) + +extern int debug; +extern const char *version; +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); + +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 data *read_data(struct epg *); +void dump_data(struct data *); + diff --git a/main.c b/main.c new file mode 100644 index 0000000..f2ecd3d --- /dev/null +++ b/main.c @@ -0,0 +1,56 @@ +/* + * Humax EPG Tool + * by af123, 2011 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lint.h" + +int debug = 0; +const char *version = "0.0.1"; +unsigned long sysopts = 0; + +int +syntax() +{ + fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version); + fprintf(stderr, + "Syntax: epg ...\n"); + fprintf(stderr, + " Commands:\n" + ); + fprintf(stderr, "\n"); + return 0; +} + +int +main(int argc, char **argv) +{ + struct section_header *h; + struct data *d; + struct epg *epg; + + if (!(epg = open_file("epg.dat"))) + return 0; + + h = read_section_header(epg); + dump_section_header(h); + + d = read_data(epg); + dump_data(d); + + close_file(epg); + + return 0; +} + diff --git a/util.c b/util.c new file mode 100644 index 0000000..b5cc8d8 --- /dev/null +++ b/util.c @@ -0,0 +1,154 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lint.h" + +inline uint32_t +read_uint32(uint8_t *p, int le) +{ + if (le) + return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; + else + return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; +} + +inline uint16_t +read_uint16(uint8_t *p, int le) +{ + if (le) + return p[1] << 8 | p[0]; + else + return p[0] << 8 | p[1]; +} + +uint8_t * +memmem(register uint8_t *mem, uint32_t mlen, + register uint8_t *pat, uint32_t plen) +{ + while (mlen >= plen) + { + if (!memcmp(mem, pat, plen)) + return mem; + mem++, mlen--; + } + return (uint8_t *)NULL; +} + +void +hexdump(uint8_t *s, uint32_t len, uint32_t o) +{ + uint16_t off; + + if (!s) + return; + + if (!len) + len = strlen((char *)s); + + for (off = 0; off < len; off += 16) + { + uint32_t i; + + printf("%08lx: ", (unsigned long)off + o); + + for (i = off; i - off < 16; i++) + { + if (i < len) + printf("%02x ", s[i] & 0xff); + else + printf(" "); + } + + printf(" "); + + for (i = off; i < len && i - off < 16; i++) + printf("%c", isprint((int)s[i]) ? s[i] : '.'); + + printf("\n"); + } +} + +void +hexstr(uint8_t *s, uint32_t len) +{ + uint16_t off; + + if (!s) + return; + + if (!len) + len = strlen((char *)s); + + for (off = 0; off < len; off += 16) + { + uint32_t i; + + for (i = off; i - off < 16; i++) + { + if (i < len) + printf("%02x", s[i] & 0xff); + } + } +} + +void +hexdump_fd(int fd, uint32_t len) +{ + off_t pos = lseek(fd, 0, SEEK_CUR); + + uint8_t *buffer; + + buffer = (uint8_t *)malloc(len); + + read(fd, buffer, len); + hexdump(buffer, len, 0); + + lseek(fd, pos, SEEK_SET); +} + +void +error(char *fmt, ...) +{ + char buf[0x400]; + va_list argp; + + va_start(argp, fmt); + vsprintf(buf, fmt, argp); + + fprintf(stderr, "%s\n", buf); + va_end(argp); + exit(1); +} + +#if defined(__MINGW32__) || defined(__linux__) + +size_t +strlcpy(char *s, const char *t, size_t n) +{ + const char *o = t; + + if (n) + do + { + if (!--n) + { + *s = 0; + break; + } + } while ((*s++ = *t++)); + if (!n) + while (*t++); + return t - o - 1; +} + +#endif +