diff options
Diffstat (limited to 'abs')
-rw-r--r-- | abs/core-testing/mythtv/stable/mythtv/PKGBUILD | 10 | ||||
-rw-r--r-- | abs/core-testing/mythtv/stable/mythtv/changeset-20877.patch | 5910 |
2 files changed, 5918 insertions, 2 deletions
diff --git a/abs/core-testing/mythtv/stable/mythtv/PKGBUILD b/abs/core-testing/mythtv/stable/mythtv/PKGBUILD index cd8e276..454e36b 100644 --- a/abs/core-testing/mythtv/stable/mythtv/PKGBUILD +++ b/abs/core-testing/mythtv/stable/mythtv/PKGBUILD @@ -1,13 +1,15 @@ pkgname=mythtv pkgver=0.21 -pkgrel=74 +pkgrel=75 pkgdesc="A Homebrew PVR project" arch=('i686' 'x86_64') depends=('bash' 'mysql-clients>=5.0' 'qt3' 'lame' 'lirc-utils' 'ffmpeg' \ 'libxvmc' 'libavc1394' 'libdc1394' 'libiec61883' 'perl-net-upnp' 'perl-time-format') backup=(etc/mythtv/mythbackend.conf etc/mythtv/mysql.txt usr/share/mythtv/is.xmlusr/share/mythtv/media_settings.xml ) source=(ftp://ftp.knoppmyth.net/R6/sources/${pkgname}-${pkgver}-fixes.tar.bz2 \ - mythbackend myththemedmenu.cpp.patch myththemedmenu.h.patch smolt_jump.patch pretty gnome_screensaver.patch mpegpspatch mythbackend.lr mythfrontend.lr) + mythbackend myththemedmenu.cpp.patch myththemedmenu.h.patch smolt_jump.patch pretty gnome_screensaver.patch mpegpspatch mythbackend.lr mythfrontend.lr + changeset-20877.patch) + #md5sums=('e316ed18d7ac837cf8c4af54b1478793' '7ef6de58240e7aad389a0b13d91b1cf6'\ # 'a0ecb7f476cb71c0c1ac90d349fc7695') @@ -33,6 +35,10 @@ build() { # cd libs/libavformat # patch -p0 < $startdir/src/mpegpspatch # cd - + +# Remove the hdhomerun changeset 20877 that prevents things from compiling. + patch -p3 < ../changeset-20877.patch + . /etc/profile.d/qt3.sh # use QT3 qmake diff --git a/abs/core-testing/mythtv/stable/mythtv/changeset-20877.patch b/abs/core-testing/mythtv/stable/mythtv/changeset-20877.patch new file mode 100644 index 0000000..b92f0c1 --- /dev/null +++ b/abs/core-testing/mythtv/stable/mythtv/changeset-20877.patch @@ -0,0 +1,5910 @@ +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/Makefile src/mythtv-0.21/libs/libmythtv/hdhomerun/Makefile +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/Makefile 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/Makefile 2009-01-09 13:14:56.000000000 +1030 +@@ -1,52 +1,21 @@ +-LIBSRCS += hdhomerun_pkt.c +-LIBSRCS += hdhomerun_debug.c +-LIBSRCS += hdhomerun_discover.c +-LIBSRCS += hdhomerun_channels.c +-LIBSRCS += hdhomerun_channelscan.c +-LIBSRCS += hdhomerun_control.c +-LIBSRCS += hdhomerun_video.c +-LIBSRCS += hdhomerun_device.c +-LIBSRCS += hdhomerun_device_selector.c + +-CC := $(CROSS_COMPILE)gcc +-STRIP := $(CROSS_COMPILE)strip ++SRCS += hdhomerun_pkt.c ++SRCS += hdhomerun_discover.c ++SRCS += hdhomerun_control.c ++SRCS += hdhomerun_video.c ++SRCS += hdhomerun_device.c ++SRCS += hdhomerun_config.c + + CFLAGS += -Wall -O2 -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith +-LDFLAGS += -lpthread +-SHARED = -shared -Wl,-soname,libhdhomerun$(LIBEXT) + +-ifeq ($(OS),Windows_NT) +- BINEXT := .exe +- LIBEXT := .dll +- LDFLAGS += -liphlpapi +-else +- LIBEXT := .so +- ifneq ($(findstring solaris,$(shell echo $$OSTYPE)),) +- LDFLAGS += -lns -lsocket +- endif +- ifneq ($(findstring darwin,$(shell echo $$OSTYPE)),) +- CFLAGS += -arch i386 -arch ppc +- LIBEXT := .dylib +- SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT) +- endif +-endif +- +-all : hdhomerun_config$(BINEXT) libhdhomerun$(LIBEXT) +- +-hdhomerun_config$(BINEXT) : hdhomerun_config.c $(LIBSRCS) +- $(CC) $(CFLAGS) $+ $(LDFLAGS) -o $@ +- $(STRIP) $@ +- +-libhdhomerun$(LIBEXT) : $(LIBSRCS) +- $(CC) $(CFLAGS) -fPIC -DDLL_EXPORT $(SHARED) $+ $(LDFLAGS) -o $@ ++hdhomerun_config : $(SRCS) ++ gcc $(CFLAGS) $(SRCS) -lpthread -o $@ ++ strip $@ ++ ++hdhomerun_config.exe : $(SRCS) ++ gcc $(CFLAGS) $(SRCS) -lpthread -liphlpapi -o $@ ++ strip $@ + + clean : +- -rm -f hdhomerun_config$(BINEXT) +- -rm -f libhdhomerun$(LIBEXT) +- +-distclean : clean +- +-%: +- @echo "(ignoring request to make $@)" +- +-.PHONY: all list clean distclean ++ rm -f hdhomerun_config ++ rm -f hdhomerun_config.exe +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,14 +1,12 @@ +-#ifndef __HDHOMERUN_INCLUDES__ +-#define __HDHOMERUN_INCLUDES__ + /* +- * hdhomerun.h ++ * hdhomerun_device.h + * +- * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -16,33 +14,13 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + #include "hdhomerun_os.h" +-#include "hdhomerun_types.h" + #include "hdhomerun_pkt.h" +-#include "hdhomerun_debug.h" + #include "hdhomerun_discover.h" + #include "hdhomerun_control.h" + #include "hdhomerun_video.h" +-#include "hdhomerun_channels.h" +-#include "hdhomerun_channelscan.h" + #include "hdhomerun_device.h" +-#include "hdhomerun_device_selector.h" +- +-#endif /* __HDHOMERUN_INCLUDES__ */ +- +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_channels.c +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_channels.h +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_channelscan.c +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_channelscan.h +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_config.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_config.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_config.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_config.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_config.c + * +- * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,34 +14,12 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + #include "hdhomerun.h" + +-/* +- * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing. +- * Attempting to restore on exit fails to restore if the program is terminated by the user. +- * Solution - set the output format each printf. +- */ +-#if defined(__WINDOWS__) +-#define printf console_printf +-#define vprintf console_vprintf +-#endif +- + static const char *appname; + + struct hdhomerun_device_t *hd; +@@ -53,8 +31,7 @@ + printf("\t%s <id> get help\n", appname); + printf("\t%s <id> get <item>\n", appname); + printf("\t%s <id> set <item> <value>\n", appname); +- printf("\t%s <id> scan <tuner> [<filename>]\n", appname); +- printf("\t%s <id> save <tuner> <filename>\n", appname); ++ printf("\t%s <id> scan <tuner> <starting channel>\n", appname); + printf("\t%s <id> upgrade <filename>\n", appname); + return -1; + } +@@ -91,29 +68,10 @@ + return FALSE; + } + +-static uint32_t parse_ip_addr(const char *str) +-{ +- unsigned long a[4]; +- if (sscanf(str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) { +- return 0; +- } +- +- return (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0)); +-} +- +-static int discover_print(char *target_ip_str) ++static int discover_print(void) + { +- uint32_t target_ip = 0; +- if (target_ip_str) { +- target_ip = parse_ip_addr(target_ip_str); +- if (target_ip == 0) { +- fprintf(stderr, "invalid ip address: %s\n", target_ip_str); +- return -1; +- } +- } +- + struct hdhomerun_discover_device_t result_list[64]; +- int count = hdhomerun_discover_find_devices_custom(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64); ++ int count = hdhomerun_discover_find_devices(HDHOMERUN_DEVICE_TYPE_TUNER, result_list, 64); + if (count < 0) { + fprintf(stderr, "error sending discover request\n"); + return -1; +@@ -136,6 +94,32 @@ + return count; + } + ++static bool_t parse_device_id_str(const char *s, uint32_t *pdevice_id, uint32_t *pdevice_ip) ++{ ++ unsigned long a[4]; ++ if (sscanf(s, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) == 4) { ++ *pdevice_id = HDHOMERUN_DEVICE_ID_WILDCARD; ++ *pdevice_ip = (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0)); ++ return TRUE; ++ } ++ ++ unsigned long device_id_raw; ++ if (sscanf(s, "%lx", &device_id_raw) != 1) { ++ fprintf(stderr, "invalid device id: %s\n", s); ++ return FALSE; ++ } ++ ++ uint32_t device_id = (uint32_t)device_id_raw; ++ if (!hdhomerun_discover_validate_device_id(device_id)) { ++ fprintf(stderr, "invalid device id: %s\n", s); ++ return FALSE; ++ } ++ ++ *pdevice_id = device_id; ++ *pdevice_ip = 0; ++ return TRUE; ++} ++ + static int cmd_get(const char *item) + { + char *ret_value; +@@ -154,7 +138,7 @@ + return 1; + } + +-static int cmd_set_internal(const char *item, const char *value) ++static int cmd_set(const char *item, const char *value) + { + char *ret_error; + if (hdhomerun_device_set_var(hd, item, value, NULL, &ret_error) < 0) { +@@ -170,260 +154,118 @@ + return 1; + } + +-static int cmd_set(const char *item, const char *value) ++static int cmd_streaminfo(const char *tuner_str) + { +- if (strcmp(value, "-") == 0) { +- char *buffer = NULL; +- size_t pos = 0; +- +- while (1) { +- buffer = (char *)realloc(buffer, pos + 1024); +- if (!buffer) { +- fprintf(stderr, "out of memory\n"); +- return -1; +- } +- +- size_t size = fread(buffer + pos, 1, 1024, stdin); +- pos += size; +- +- if (size < 1024) { +- break; +- } +- } +- +- buffer[pos] = 0; +- +- int ret = cmd_set_internal(item, buffer); +- +- free(buffer); +- return ret; +- } +- +- return cmd_set_internal(item, value); +-} +- +-static bool_t sigabort = FALSE; +- +-static void signal_abort(int arg) +-{ +- sigabort = TRUE; +-} +- +-static void cmd_scan_printf(FILE *fp, const char *fmt, ...) +-{ +- va_list ap; +- va_start(ap, fmt); +- +- if (fp) { +- va_list apc; +- va_copy(apc, ap); +- +- vfprintf(fp, fmt, apc); +- fflush(fp); +- +- va_end(apc); +- } +- +- vprintf(fmt, ap); +- fflush(stdout); +- +- va_end(ap); ++ fprintf(stderr, "streaminfo: use \"get /tuner<n>/streaminfo\"\n"); ++ return -1; + } + +-static int cmd_scan(const char *tuner_str, const char *filename) ++static int cmd_scan(const char *tuner_str, const char *start_value) + { +- if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) { ++ unsigned int tuner; ++ if (sscanf(tuner_str, "%u", &tuner) != 1) { + fprintf(stderr, "invalid tuner number\n"); + return -1; + } + +- char *ret_error; +- if (hdhomerun_device_tuner_lockkey_request(hd, &ret_error) <= 0) { +- fprintf(stderr, "failed to lock tuner\n"); +- if (ret_error) { +- fprintf(stderr, "%s\n", ret_error); +- } +- return -1; +- } ++ hdhomerun_device_set_tuner(hd, tuner); + +- hdhomerun_device_set_tuner_target(hd, "none"); +- +- char *channelmap; +- if (hdhomerun_device_get_tuner_channelmap(hd, &channelmap) <= 0) { +- fprintf(stderr, "failed to query channelmap from device\n"); +- return -1; ++ char channel_str[64]; ++ strncpy(channel_str, start_value, sizeof(channel_str)); ++ channel_str[sizeof(channel_str) - 8] = 0; ++ ++ char *channel_number_ptr = strrchr(channel_str, ':'); ++ if (!channel_number_ptr) { ++ channel_number_ptr = channel_str; ++ } else { ++ channel_number_ptr++; + } + +- const char *channelmap_scan_group = hdhomerun_channelmap_get_channelmap_scan_group(channelmap); +- if (!channelmap_scan_group) { +- fprintf(stderr, "unknown channelmap '%s'\n", channelmap); ++ unsigned int channel_number = atol(channel_number_ptr); ++ if (channel_number == 0) { ++ fprintf(stderr, "invalid starting channel\n"); + return -1; + } + +- if (hdhomerun_device_channelscan_init(hd, channelmap_scan_group) <= 0) { +- fprintf(stderr, "failed to initialize channel scan\n"); ++ /* Test starting channel. */ ++ int ret = hdhomerun_device_set_tuner_channel(hd, channel_str); ++ if (ret < 0) { ++ fprintf(stderr, "communication error sending request to hdhomerun device\n"); + return -1; + } +- +- FILE *fp = NULL; +- if (filename) { +- fp = fopen(filename, "w"); +- if (!fp) { +- fprintf(stderr, "unable to create file: %s\n", filename); +- return -1; +- } ++ if (ret == 0) { ++ fprintf(stderr, "invalid starting channel\n"); ++ return -1; + } + +- signal(SIGINT, signal_abort); +- signal(SIGPIPE, signal_abort); ++ while (1) { ++ /* Update channel value */ ++ sprintf(channel_number_ptr, "%u", channel_number); + +- int ret = 0; +- while (!sigabort) { +- struct hdhomerun_channelscan_result_t result; +- ret = hdhomerun_device_channelscan_advance(hd, &result); +- if (ret <= 0) { +- break; ++ /* Set channel. */ ++ ret = hdhomerun_device_set_tuner_channel(hd, channel_str); ++ if (ret < 0) { ++ fprintf(stderr, "communication error sending request to hdhomerun device\n"); ++ return -1; + } +- +- cmd_scan_printf(fp, "SCANNING: %lu (%s)\n", +- result.frequency, result.channel_str +- ); +- +- ret = hdhomerun_device_channelscan_detect(hd, &result); +- if (ret <= 0) { +- break; ++ if (ret == 0) { ++ return 0; + } + +- cmd_scan_printf(fp, "LOCK: %s (ss=%u snq=%u seq=%u)\n", +- result.status.lock_str, result.status.signal_strength, +- result.status.signal_to_noise_quality, result.status.symbol_error_quality +- ); ++ /* Wait 1.5s for lock (qam auto is the slowest to lock). */ ++ usleep(HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME * 1000); + +- if (result.transport_stream_id_detected) { +- cmd_scan_printf(fp, "TSID: 0x%04X\n", result.transport_stream_id); ++ /* Get status to check for signal. Quality numbers will not be valid yet. */ ++ struct hdhomerun_tuner_status_t status; ++ if (hdhomerun_device_get_tuner_status(hd, &status) < 0) { ++ fprintf(stderr, "communication error sending request to hdhomerun device\n"); ++ return -1; + } + +- int i; +- for (i = 0; i < result.program_count; i++) { +- struct hdhomerun_channelscan_program_t *program = &result.programs[i]; +- cmd_scan_printf(fp, "PROGRAM %s\n", program->program_str); ++ /* If no signal then advance to next channel. */ ++ if (status.signal_strength == 0) { ++ printf("%s: no signal\n", channel_str); ++ channel_number++; ++ continue; + } +- } +- +- hdhomerun_device_tuner_lockkey_release(hd); + +- if (fp) { +- fclose(fp); +- } +- if (ret < 0) { +- fprintf(stderr, "communication error sending request to hdhomerun device\n"); +- } +- return ret; +-} +- +-static int cmd_save(const char *tuner_str, const char *filename) +-{ +- if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) { +- fprintf(stderr, "invalid tuner number\n"); +- return -1; +- } ++ /* Wait for 2s. */ ++ usleep(HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME * 1000); + +- FILE *fp; +- if (strcmp(filename, "null") == 0) { +- fp = NULL; +- } else if (strcmp(filename, "-") == 0) { +- fp = stdout; +- } else { +- fp = fopen(filename, "wb"); +- if (!fp) { +- fprintf(stderr, "unable to create file %s\n", filename); ++ /* Get status to check quality numbers. */ ++ if (hdhomerun_device_get_tuner_status(hd, &status) < 0) { ++ fprintf(stderr, "communication error sending request to hdhomerun device\n"); + return -1; + } +- } +- +- int ret = hdhomerun_device_stream_start(hd); +- if (ret <= 0) { +- fprintf(stderr, "unable to start stream\n"); +- if (fp && fp != stdout) { +- fclose(fp); +- } +- return ret; +- } +- +- signal(SIGINT, signal_abort); +- signal(SIGPIPE, signal_abort); +- +- struct hdhomerun_video_stats_t stats_old, stats_cur; +- hdhomerun_device_get_video_stats(hd, &stats_old); +- +- uint64_t next_progress = getcurrenttime() + 1000; +- +- while (!sigabort) { +- uint64_t loop_start_time = getcurrenttime(); +- +- size_t actual_size; +- uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size); +- if (!ptr) { +- msleep(64); ++ if (status.signal_strength == 0) { ++ printf("%s: no signal\n", channel_str); ++ channel_number++; + continue; + } ++ printf("%s: ss=%u snq=%u seq=%u\n", channel_str, status.signal_strength, status.signal_to_noise_quality, status.symbol_error_quality); + +- if (fp) { +- if (fwrite(ptr, 1, actual_size, fp) != actual_size) { +- fprintf(stderr, "error writing output\n"); +- return -1; +- } ++ /* Detect sub channels. */ ++ usleep(4 * 1000000); ++ char *streaminfo; ++ if (hdhomerun_device_get_tuner_streaminfo(hd, &streaminfo) <= 0) { ++ channel_number++; ++ continue; + } +- +- if (loop_start_time >= next_progress) { +- next_progress += 1000; +- if (loop_start_time >= next_progress) { +- next_progress = loop_start_time + 1000; +- } +- +- hdhomerun_device_get_video_stats(hd, &stats_cur); +- +- if (stats_cur.overflow_error_count > stats_old.overflow_error_count) { +- fprintf(stderr, "o"); +- } else if (stats_cur.network_error_count > stats_old.network_error_count) { +- fprintf(stderr, "n"); +- } else if (stats_cur.transport_error_count > stats_old.transport_error_count) { +- fprintf(stderr, "t"); +- } else if (stats_cur.sequence_error_count > stats_old.sequence_error_count) { +- fprintf(stderr, "s"); +- } else { +- fprintf(stderr, "."); ++ while (1) { ++ char *end = strchr(streaminfo, '\n'); ++ if (!end) { ++ break; + } + +- stats_old = stats_cur; +- fflush(stderr); +- } ++ *end++ = 0; ++ printf("program %s\n", streaminfo); + +- int32_t delay = 64 - (int32_t)(getcurrenttime() - loop_start_time); +- if (delay <= 0) { +- continue; ++ streaminfo = end; + } + +- msleep(delay); +- } +- +- if (fp) { +- fclose(fp); ++ /* Advance to next channel. */ ++ channel_number++; + } +- +- hdhomerun_device_stream_stop(hd); +- hdhomerun_device_get_video_stats(hd, &stats_cur); +- +- fprintf(stderr, "\n"); +- fprintf(stderr, "-- Video statistics --\n"); +- fprintf(stderr, "%u packets received, %u overflow errors, %u network errors, %u transport errors, %u sequence errors\n", +- (unsigned int)stats_cur.packet_count, +- (unsigned int)stats_cur.overflow_error_count, +- (unsigned int)stats_cur.network_error_count, +- (unsigned int)stats_cur.transport_error_count, +- (unsigned int)stats_cur.sequence_error_count); +- +- return 0; + } + + static int cmd_upgrade(const char *filename) +@@ -434,98 +276,16 @@ + return -1; + } + +- printf("uploading firmware...\n"); + if (hdhomerun_device_upgrade(hd, fp) <= 0) { + fprintf(stderr, "error sending upgrade file to hdhomerun device\n"); + fclose(fp); + return -1; + } +- sleep(2); +- +- printf("upgrading firmware...\n"); +- sleep(8); +- +- printf("rebooting...\n"); +- int count = 0; +- char *version_str; +- while (1) { +- if (hdhomerun_device_get_version(hd, &version_str, NULL) >= 0) { +- break; +- } +- +- count++; +- if (count > 30) { +- fprintf(stderr, "error finding device after firmware upgrade\n"); +- fclose(fp); +- return -1; +- } + +- sleep(1); +- } +- +- printf("upgrade complete - now running firmware %s\n", version_str); ++ printf("upgrade complete\n"); + return 0; + } + +-static int cmd_execute(void) +-{ +- char *ret_value; +- char *ret_error; +- if (hdhomerun_device_get_var(hd, "/sys/boot", &ret_value, &ret_error) < 0) { +- fprintf(stderr, "communication error sending request to hdhomerun device\n"); +- return -1; +- } +- +- if (ret_error) { +- printf("%s\n", ret_error); +- return 0; +- } +- +- char *end = ret_value + strlen(ret_value); +- char *pos = ret_value; +- +- while (1) { +- if (pos >= end) { +- break; +- } +- +- char *eol_r = strchr(pos, '\r'); +- if (!eol_r) { +- eol_r = end; +- } +- +- char *eol_n = strchr(pos, '\n'); +- if (!eol_n) { +- eol_n = end; +- } +- +- char *eol = eol_r; +- if (eol_n < eol) { +- eol = eol_n; +- } +- +- char *sep = strchr(pos, ' '); +- if (!sep || sep > eol) { +- pos = eol + 1; +- continue; +- } +- +- *sep = 0; +- *eol = 0; +- +- char *item = pos; +- char *value = sep + 1; +- +- printf("set %s \"%s\"\n", item, value); +- +- cmd_set_internal(item, value); +- +- pos = eol + 1; +- } +- +- return 1; +-} +- + static int main_cmd(int argc, char *argv[]) + { + if (argc < 1) { +@@ -534,17 +294,6 @@ + + char *cmd = *argv++; argc--; + +- if (contains(cmd, "key")) { +- if (argc < 2) { +- return help(); +- } +- uint32_t lockkey = strtoul(argv[0], NULL, 0); +- hdhomerun_device_tuner_lockkey_use_value(hd, lockkey); +- +- cmd = argv[1]; +- argv+=2; argc-=2; +- } +- + if (contains(cmd, "get")) { + if (argc < 1) { + return help(); +@@ -559,22 +308,18 @@ + return cmd_set(argv[0], argv[1]); + } + +- if (contains(cmd, "scan")) { ++ if (contains(cmd, "streaminfo")) { + if (argc < 1) { + return help(); + } +- if (argc < 2) { +- return cmd_scan(argv[0], NULL); +- } else { +- return cmd_scan(argv[0], argv[1]); +- } ++ return cmd_streaminfo(argv[0]); + } + +- if (contains(cmd, "save")) { ++ if (contains(cmd, "scan")) { + if (argc < 2) { + return help(); + } +- return cmd_save(argv[0], argv[1]); ++ return cmd_scan(argv[0], argv[1]); + } + + if (contains(cmd, "upgrade")) { +@@ -584,17 +329,16 @@ + return cmd_upgrade(argv[0]); + } + +- if (contains(cmd, "execute")) { +- return cmd_execute(); +- } +- + return help(); + } + + static int main_internal(int argc, char *argv[]) + { + #if defined(__WINDOWS__) +- /* Initialize network socket support. */ ++ //Start pthreads ++ pthread_win32_process_attach_np(); ++ ++ // Start WinSock + WORD wVersionRequested = MAKEWORD(2, 0); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); +@@ -613,36 +357,35 @@ + return help(); + } + if (contains(id_str, "discover")) { +- if (argc < 1) { +- return discover_print(NULL); +- } else { +- return discover_print(argv[0]); +- } ++ return discover_print(); + } + +- /* Device object. */ +- hd = hdhomerun_device_create_from_str(id_str, NULL); +- if (!hd) { +- fprintf(stderr, "invalid device id: %s\n", id_str); ++ /* Device ID. */ ++ uint32_t device_id, device_ip; ++ if (!parse_device_id_str(id_str, &device_id, &device_ip)) { + return -1; + } + +- /* Device ID check. */ +- uint32_t device_id_requested = hdhomerun_device_get_device_id_requested(hd); +- if (!hdhomerun_discover_validate_device_id(device_id_requested)) { +- fprintf(stderr, "invalid device id: %08lX\n", (unsigned long)device_id_requested); ++ /* Device object. */ ++ hd = hdhomerun_device_create(device_id, device_ip, 0); ++ if (!hd) { ++ fprintf(stderr, "unable to create device\n"); ++ return -1; + } + +- /* Connect to device and check model. */ +- const char *model = hdhomerun_device_get_model_str(hd); +- if (!model) { ++ /* Connect to device and check firmware version. */ ++ int ret = hdhomerun_device_firmware_version_check(hd, 0); ++ if (ret < 0) { + fprintf(stderr, "unable to connect to device\n"); + hdhomerun_device_destroy(hd); + return -1; + } ++ if (ret == 0) { ++ fprintf(stderr, "WARNING: firmware upgrade needed for all operations to function\n"); ++ } + + /* Command. */ +- int ret = main_cmd(argc, argv); ++ ret = main_cmd(argc, argv); + + /* Cleanup. */ + hdhomerun_device_destroy(hd); +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_control.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_control.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_control.c + * +- * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,119 +14,83 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include "hdhomerun.h" +- +-#define HDHOMERUN_CONTROL_SEND_TIMEOUT 5000 +-#define HDHOMERUN_CONTROL_RECV_TIMEOUT 5000 +-#define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000 ++#include "hdhomerun_os.h" ++#include "hdhomerun_pkt.h" ++#include "hdhomerun_discover.h" ++#include "hdhomerun_control.h" + + struct hdhomerun_control_sock_t { +- uint32_t desired_device_id; +- uint32_t desired_device_ip; +- uint32_t actual_device_id; +- uint32_t actual_device_ip; ++ uint32_t device_id; ++ uint32_t device_ip; + int sock; +- struct hdhomerun_debug_t *dbg; +- struct hdhomerun_pkt_t tx_pkt; +- struct hdhomerun_pkt_t rx_pkt; ++ uint8_t buffer[16384]; + }; + +-static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs) +-{ +- if (cs->sock == -1) { +- return; +- } +- +- close(cs->sock); +- cs->sock = -1; +-} +- +-void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip) +-{ +- hdhomerun_control_close_sock(cs); +- +- cs->desired_device_id = device_id; +- cs->desired_device_ip = device_ip; +- cs->actual_device_id = 0; +- cs->actual_device_ip = 0; +-} +- +-struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg) ++struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip) + { +- struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)calloc(1, sizeof(struct hdhomerun_control_sock_t)); ++ struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)malloc(sizeof(struct hdhomerun_control_sock_t)); + if (!cs) { +- hdhomerun_debug_printf(dbg, "hdhomerun_control_create: failed to allocate control object\n"); + return NULL; + } +- +- cs->dbg = dbg; ++ ++ cs->device_id = device_id; ++ cs->device_ip = device_ip; + cs->sock = -1; +- hdhomerun_control_set_device(cs, device_id, device_ip); + + return cs; + } + + void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs) + { +- hdhomerun_control_close_sock(cs); ++ if (cs->sock != -1) { ++ close(cs->sock); ++ } + free(cs); + } + ++static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs) ++{ ++ close(cs->sock); ++ cs->sock = -1; ++} ++ + static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs) + { + if (cs->sock != -1) { + return TRUE; + } + +- if ((cs->desired_device_id == 0) && (cs->desired_device_ip == 0)) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n"); +- return FALSE; +- } +- +- /* Find device. */ +- struct hdhomerun_discover_device_t result; +- if (hdhomerun_discover_find_devices_custom(cs->desired_device_ip, HDHOMERUN_DEVICE_TYPE_WILDCARD, cs->desired_device_id, &result, 1) <= 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: device not found\n"); +- return FALSE; ++ /* Find ip address. */ ++ uint32_t device_ip = cs->device_ip; ++ if (device_ip == 0) { ++ struct hdhomerun_discover_device_t result; ++ if (hdhomerun_discover_find_device(cs->device_id, &result) <= 0) { ++ return FALSE; ++ } ++ device_ip = result.ip_addr; + } +- cs->actual_device_ip = result.ip_addr; +- cs->actual_device_id = result.device_id; + + /* Create socket. */ + cs->sock = (int)socket(AF_INET, SOCK_STREAM, 0); + if (cs->sock == -1) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", sock_getlasterror); + return FALSE; + } + + /* Set timeouts. */ +- setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, HDHOMERUN_CONTROL_SEND_TIMEOUT); +- setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, HDHOMERUN_CONTROL_RECV_TIMEOUT); ++ setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000); ++ setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); + + /* Initiate connection. */ + struct sockaddr_in sock_addr; + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; +- sock_addr.sin_addr.s_addr = htonl(cs->actual_device_ip); ++ sock_addr.sin_addr.s_addr = htonl(device_ip); + sock_addr.sin_port = htons(HDHOMERUN_CONTROL_TCP_PORT); + if (connect(cs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to connect (%d)\n", sock_getlasterror); + hdhomerun_control_close_sock(cs); + return FALSE; + } +@@ -135,215 +99,125 @@ + return TRUE; + } + +-uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs) +-{ +- if (!hdhomerun_control_connect_sock(cs)) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_id: connect failed\n"); +- return 0; +- } +- +- return cs->actual_device_id; +-} +- +-uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs) +-{ +- if (!hdhomerun_control_connect_sock(cs)) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_ip: connect failed\n"); +- return 0; +- } +- +- return cs->actual_device_ip; +-} +- +-uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs) +-{ +- return cs->desired_device_id; +-} +- +-uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs) +-{ +- return cs->desired_device_ip; +-} +- + uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs) + { + if (!hdhomerun_control_connect_sock(cs)) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: connect failed\n"); + return 0; + } + + struct sockaddr_in sock_addr; + socklen_t sockaddr_size = sizeof(sock_addr); + if (getsockname(cs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: getsockname failed (%d)\n", sock_getlasterror); + return 0; + } + + return ntohl(sock_addr.sin_addr.s_addr); + } + +-static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt) ++static int hdhomerun_control_send(struct hdhomerun_control_sock_t *cs, uint8_t *start, uint8_t *end) + { +- int length = (int)(tx_pkt->end - tx_pkt->start); +- if (send(cs->sock, (char *)tx_pkt->start, (int)length, 0) != length) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_sock: send failed (%d)\n", sock_getlasterror); +- hdhomerun_control_close_sock(cs); ++ int length = (int)(end - start); ++ if (send(cs->sock, (char *)start, (int)length, 0) != length) { + return -1; + } + +- return 1; ++ return length; + } + +-static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout) ++static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit) + { +- uint64_t stop_time = getcurrenttime() + recv_timeout; +- hdhomerun_pkt_reset(rx_pkt); ++ struct timeval t; ++ t.tv_sec = 0; ++ t.tv_usec = 250000; + +- while (getcurrenttime() < stop_time) { +- struct timeval t; +- t.tv_sec = 0; +- t.tv_usec = 250000; +- +- fd_set readfds; +- FD_ZERO(&readfds); +- FD_SET(cs->sock, &readfds); +- +- if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: select failed (%d)\n", sock_getlasterror); +- hdhomerun_control_close_sock(cs); +- return -1; +- } +- +- if (!FD_ISSET(cs->sock, &readfds)) { +- continue; +- } +- +- int rx_length = recv(cs->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0); +- if (rx_length <= 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: recv failed (%d)\n", sock_getlasterror); +- hdhomerun_control_close_sock(cs); +- return -1; +- } +- rx_pkt->end += rx_length; ++ fd_set readfds; ++ FD_ZERO(&readfds); ++ FD_SET(cs->sock, &readfds); + +- int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype); +- if (ret < 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n"); +- hdhomerun_control_close_sock(cs); +- return -1; +- } +- if (ret == 0) { +- continue; +- } ++ if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { ++ return -1; ++ } + +- return 1; ++ if (!FD_ISSET(cs->sock, &readfds)) { ++ return 0; + } + +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n"); +- hdhomerun_control_close_sock(cs); +- return -1; ++ int length = recv(cs->sock, (char *)buffer, (int)(limit - buffer), 0); ++ if (length <= 0) { ++ return -1; ++ } ++ ++ return length; + } + +-static int hdhomerun_control_send_recv_internal(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type, uint64_t recv_timeout) ++static int hdhomerun_control_recv(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit) + { +- hdhomerun_pkt_seal_frame(tx_pkt, type); ++ uint64_t timeout = getcurrenttime() + 1000; ++ uint8_t *ptr = buffer; + +- int i; +- for (i = 0; i < 2; i++) { +- if (cs->sock == -1) { +- if (!hdhomerun_control_connect_sock(cs)) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n"); +- return -1; +- } ++ while (getcurrenttime() < timeout) { ++ int length = hdhomerun_control_recv_sock(cs, ptr, limit); ++ if (length < 0) { ++ return -1; + } +- +- if (hdhomerun_control_send_sock(cs, tx_pkt) < 0) { ++ if (length == 0) { + continue; + } +- if (!rx_pkt) { +- return 1; +- } ++ ptr += length; + +- uint16_t rsp_type; +- if (hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout) < 0) { ++ if (buffer + HDHOMERUN_MIN_PEEK_LENGTH > limit) { + continue; + } +- if (rsp_type != type + 1) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: unexpected frame type\n"); +- hdhomerun_control_close_sock(cs); ++ ++ length = (int)hdhomerun_peek_packet_length(buffer); ++ if (buffer + length > limit) { + continue; + } + +- return 1; ++ return length; + } + +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: failed\n"); + return -1; + } + +-int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type) ++static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror) + { +- return hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, type, HDHOMERUN_CONTROL_RECV_TIMEOUT); +-} +- +-static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror) +-{ +- struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt; +- struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt; +- +- /* Request. */ +- hdhomerun_pkt_reset(tx_pkt); +- +- int name_len = (int)strlen(name) + 1; +- if (tx_pkt->end + 3 + name_len > tx_pkt->limit) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); ++ /* Send request. */ ++ uint8_t *ptr = cs->buffer; ++ hdhomerun_write_get_set_request(&ptr, name, value); ++ if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { + return -1; + } +- hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME); +- hdhomerun_pkt_write_var_length(tx_pkt, name_len); +- hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len); + +- if (value) { +- int value_len = (int)strlen(value) + 1; +- if (tx_pkt->end + 3 + value_len > tx_pkt->limit) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); +- return -1; +- } +- hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE); +- hdhomerun_pkt_write_var_length(tx_pkt, value_len); +- hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len); ++ /* Receive response. */ ++ int length = hdhomerun_control_recv(cs, cs->buffer, cs->buffer + sizeof(cs->buffer)); ++ if (length <= 0) { ++ return -1; + } + +- if (lockkey != 0) { +- if (tx_pkt->end + 6 > tx_pkt->limit) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); +- return -1; +- } +- hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_LOCKKEY); +- hdhomerun_pkt_write_var_length(tx_pkt, 4); +- hdhomerun_pkt_write_u32(tx_pkt, lockkey); ++ /* Parse response. */ ++ ptr = cs->buffer; ++ uint8_t *end = ptr + length; ++ int type = hdhomerun_process_packet(&ptr, &end); ++ if (type < 0) { ++ return -1; + } +- +- /* Send/Recv. */ +- if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_GETSET_REQ, HDHOMERUN_CONTROL_RECV_TIMEOUT) < 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: send/recv error\n"); ++ if (type != HDHOMERUN_TYPE_GETSET_RPY) { + return -1; + } + +- /* Response. */ +- while (1) { ++ while (ptr < end) { + uint8_t tag; + size_t len; +- uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); +- if (!next) { ++ uint8_t *val; ++ if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &val) < 0) { + break; + } +- + switch (tag) { + case HDHOMERUN_TAG_GETSET_VALUE: + if (pvalue) { +- *pvalue = (char *)rx_pkt->pos; +- rx_pkt->pos[len] = 0; ++ *pvalue = (char *)val; ++ val[len] = 0; + } + if (perror) { + *perror = NULL; +@@ -351,48 +225,59 @@ + return 1; + + case HDHOMERUN_TAG_ERROR_MESSAGE: +- rx_pkt->pos[len] = 0; +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: %s\n", rx_pkt->pos); +- + if (pvalue) { + *pvalue = NULL; + } + if (perror) { +- *perror = (char *)rx_pkt->pos; ++ *perror = (char *)val; ++ val[len] = 0; + } +- + return 0; + } +- +- rx_pkt->pos = next; + } + +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: missing response tags\n"); + return -1; + } + + int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror) + { +- return hdhomerun_control_get_set(cs, name, NULL, 0, pvalue, perror); ++ if (!hdhomerun_control_connect_sock(cs)) { ++ return -1; ++ } ++ ++ int ret = hdhomerun_control_get_set(cs, name, NULL, pvalue, perror); ++ if (ret < 0) { ++ hdhomerun_control_close_sock(cs); ++ return -1; ++ } ++ ++ return ret; + } + + int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror) + { +- return hdhomerun_control_get_set(cs, name, value, 0, pvalue, perror); +-} ++ if (!hdhomerun_control_connect_sock(cs)) { ++ return -1; ++ } + +-int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror) +-{ +- return hdhomerun_control_get_set(cs, name, value, lockkey, pvalue, perror); ++ int ret = hdhomerun_control_get_set(cs, name, value, pvalue, perror); ++ if (ret < 0) { ++ hdhomerun_control_close_sock(cs); ++ return -1; ++ } ++ ++ return ret; + } + + int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file) + { +- struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt; +- struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt; ++ if (!hdhomerun_control_connect_sock(cs)) { ++ return -1; ++ } ++ + uint32_t sequence = 0; ++ uint8_t *ptr; + +- /* Upload. */ + while (1) { + uint8_t data[256]; + size_t length = fread(data, 1, 256, upgrade_file); +@@ -400,12 +285,10 @@ + break; + } + +- hdhomerun_pkt_reset(tx_pkt); +- hdhomerun_pkt_write_u32(tx_pkt, sequence); +- hdhomerun_pkt_write_mem(tx_pkt, data, length); +- +- if (hdhomerun_control_send_recv_internal(cs, tx_pkt, NULL, HDHOMERUN_TYPE_UPGRADE_REQ, 0) < 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: send/recv failed\n"); ++ ptr = cs->buffer; ++ hdhomerun_write_upgrade_request(&ptr, sequence, data, length); ++ if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { ++ hdhomerun_control_close_sock(cs); + return -1; + } + +@@ -414,40 +297,15 @@ + + if (sequence == 0) { + /* No data in file. Error, but no need to close connection. */ +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: zero length file\n"); + return 0; + } + +- /* Execute upgrade. */ +- hdhomerun_pkt_reset(tx_pkt); +- hdhomerun_pkt_write_u32(tx_pkt, 0xFFFFFFFF); +- +- if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_UPGRADE_REQ, HDHOMERUN_CONTROL_UPGRADE_TIMEOUT) < 0) { +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: send/recv failed\n"); ++ ptr = cs->buffer; ++ hdhomerun_write_upgrade_request(&ptr, 0xFFFFFFFF, NULL, 0); ++ if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { ++ hdhomerun_control_close_sock(cs); + return -1; + } + +- /* Check response. */ +- while (1) { +- uint8_t tag; +- size_t len; +- uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); +- if (!next) { +- break; +- } +- +- switch (tag) { +- case HDHOMERUN_TAG_ERROR_MESSAGE: +- rx_pkt->pos[len] = 0; +- hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: %s\n", (char *)rx_pkt->pos); +- return 0; +- +- default: +- break; +- } +- +- rx_pkt->pos = next; +- } +- + return 1; + } +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_control.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_control.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_control.h + * +- * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,20 +14,8 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifdef __cplusplus + extern "C" { +@@ -43,26 +31,13 @@ + * + * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. + * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. +- * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. + * + * Returns a pointer to the newly created control socket. + * + * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. + */ +-extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg); +-extern LIBTYPE void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs); +- +-/* +- * Get the actual device id or ip of the device. +- * +- * Returns 0 if the device id cannot be determined. +- */ +-extern LIBTYPE uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs); +-extern LIBTYPE uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs); +-extern LIBTYPE uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs); +-extern LIBTYPE uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs); +- +-extern LIBTYPE void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip); ++extern struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip); ++extern void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs); + + /* + * Get the local machine IP address used when communicating with the device. +@@ -71,12 +46,7 @@ + * + * Returns 32-bit IP address with native endianness, or 0 on error. + */ +-extern LIBTYPE uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs); +- +-/* +- * Low-level communication. +- */ +-extern LIBTYPE int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type); ++extern uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs); + + /* + * Get/set a control variable on the device. +@@ -95,9 +65,8 @@ + * Returns 0 if the operation was rejected (pvalue NULL, perror set). + * Returns -1 if a communication error occurs. + */ +-extern LIBTYPE int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror); +-extern LIBTYPE int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror); +-extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror); ++extern int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror); ++extern int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror); + + /* + * Upload new firmware to the device. +@@ -108,7 +77,7 @@ + * Returns 0 if the upload was rejected. + * Returns -1 if an error occurs. + */ +-extern LIBTYPE int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file); ++extern int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file); + + #ifdef __cplusplus + } +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_debug.c +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_debug.h +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_device.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_device.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* +- * hdhomerun_device.c ++ * hdhomerun_record.c + * +- * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,92 +14,43 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include "hdhomerun.h" ++#include "hdhomerun_os.h" ++#include "hdhomerun_pkt.h" ++#include "hdhomerun_control.h" ++#include "hdhomerun_video.h" ++#include "hdhomerun_device.h" + + struct hdhomerun_device_t { + struct hdhomerun_control_sock_t *cs; + struct hdhomerun_video_sock_t *vs; +- struct hdhomerun_debug_t *dbg; +- struct hdhomerun_channelscan_t *scan; +- uint32_t device_id; + unsigned int tuner; +- uint32_t lockkey; +- char name[32]; +- char model[32]; ++ char result_buffer[1024]; + }; + +-static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd) +-{ +- /* Clear cached information. */ +- *hd->model = 0; +- +- /* New name. */ +- sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner); +-} +- +-void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip) +-{ +- hdhomerun_control_set_device(hd->cs, device_id, device_ip); +- +- if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) { +- device_id = hdhomerun_control_get_device_id(hd->cs); +- } +- +- hd->device_id = device_id; +- hdhomerun_device_set_update(hd); +-} +- +-void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner) +-{ +- hd->tuner = tuner; +- hdhomerun_device_set_update(hd); +-} +- +-struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg) ++struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner) + { + struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t)); + if (!hd) { +- hdhomerun_debug_printf(dbg, "hdhomerun_device_create: failed to allocate device object\n"); + return NULL; + } + +- hd->dbg = dbg; ++ hd->tuner = tuner; + +- hd->cs = hdhomerun_control_create(0, 0, hd->dbg); ++ hd->cs = hdhomerun_control_create(device_id, device_ip); + if (!hd->cs) { +- hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to create control object\n"); + free(hd); + return NULL; + } + +- hdhomerun_device_set_device(hd, device_id, device_ip); +- hdhomerun_device_set_tuner(hd, tuner); +- + return hd; + } + + void hdhomerun_device_destroy(struct hdhomerun_device_t *hd) + { +- if (hd->scan) { +- channelscan_destroy(hd->scan); +- } +- + if (hd->vs) { + hdhomerun_video_destroy(hd->vs); + } +@@ -109,152 +60,9 @@ + free(hd); + } + +-static bool_t is_hex_char(char c) +-{ +- if ((c >= '0') && (c <= '9')) { +- return TRUE; +- } +- if ((c >= 'A') && (c <= 'F')) { +- return TRUE; +- } +- if ((c >= 'a') && (c <= 'f')) { +- return TRUE; +- } +- return FALSE; +-} +- +-static struct hdhomerun_device_t *hdhomerun_device_create_from_str_device_id(const char *device_str, struct hdhomerun_debug_t *dbg) +-{ +- int i; +- const char *ptr = device_str; +- for (i = 0; i < 8; i++) { +- if (!is_hex_char(*ptr++)) { +- return NULL; +- } +- } +- +- if (*ptr == 0) { +- unsigned long device_id; +- if (sscanf(device_str, "%lx", &device_id) != 1) { +- return NULL; +- } +- return hdhomerun_device_create((uint32_t)device_id, 0, 0, dbg); +- } +- +- if (*ptr == '-') { +- unsigned long device_id; +- unsigned int tuner; +- if (sscanf(device_str, "%lx-%u", &device_id, &tuner) != 2) { +- return NULL; +- } +- return hdhomerun_device_create((uint32_t)device_id, 0, tuner, dbg); +- } +- +- return NULL; +-} +- +-static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg) +-{ +- unsigned long a[4]; +- if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) { +- return NULL; +- } +- +- unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0); +- return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg); +-} +- +-static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg) +-{ +-#if defined(__CYGWIN__) +- return NULL; +-#else +- struct addrinfo hints; +- memset(&hints, 0, sizeof(hints)); +- hints.ai_family = AF_INET; +- hints.ai_socktype = SOCK_STREAM; +- hints.ai_protocol = IPPROTO_TCP; +- +- struct addrinfo *sock_info; +- if (getaddrinfo(device_str, "65001", &hints, &sock_info) != 0) { +- return NULL; +- } +- +- struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr; +- uint32_t device_ip = ntohl(sock_addr->sin_addr.s_addr); +- freeaddrinfo(sock_info); +- +- if (device_ip == 0) { +- return NULL; +- } +- +- return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg); +-#endif +-} +- +-struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg) +-{ +- struct hdhomerun_device_t *device = hdhomerun_device_create_from_str_device_id(device_str, dbg); +- if (device) { +- return device; +- } +- +- device = hdhomerun_device_create_from_str_ip(device_str, dbg); +- if (device) { +- return device; +- } +- +- device = hdhomerun_device_create_from_str_dns(device_str, dbg); +- if (device) { +- return device; +- } +- +- return NULL; +-} +- +-int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str) +-{ +- unsigned int tuner; +- if (sscanf(tuner_str, "%u", &tuner) == 1) { +- hdhomerun_device_set_tuner(hd, tuner); +- return 1; +- } +- if (sscanf(tuner_str, "/tuner%u", &tuner) == 1) { +- hdhomerun_device_set_tuner(hd, tuner); +- return 1; +- } +- +- return -1; +-} +- +-const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd) +-{ +- return hd->name; +-} +- +-uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd) +-{ +- return hdhomerun_control_get_device_id(hd->cs); +-} +- +-uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd) +-{ +- return hdhomerun_control_get_device_ip(hd->cs); +-} +- +-uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd) +-{ +- return hdhomerun_control_get_device_id_requested(hd->cs); +-} +- +-uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd) +-{ +- return hdhomerun_control_get_device_ip_requested(hd->cs); +-} +- +-unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd) ++void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner) + { +- return hd->tuner; ++ hd->tuner = tuner; + } + + struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd) +@@ -264,16 +72,9 @@ + + struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd) + { +- if (hd->vs) { +- return hd->vs; +- } +- +- hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg); + if (!hd->vs) { +- hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n"); +- return NULL; ++ hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); + } +- + return hd->vs; + } + +@@ -295,73 +96,7 @@ + return (uint32_t)value; + } + +-static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status) +-{ +- if (strcmp(status->lock_str, "8vsb") == 0) { +- return TRUE; +- } +- if (strncmp(status->lock_str, "t8", 2) == 0) { +- return TRUE; +- } +- if (strncmp(status->lock_str, "t7", 2) == 0) { +- return TRUE; +- } +- if (strncmp(status->lock_str, "t6", 2) == 0) { +- return TRUE; +- } +- +- return FALSE; +-} +- +-uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status) +-{ +- unsigned int ss_yellow_min; +- unsigned int ss_green_min; +- +- if (!status->lock_supported) { +- return HDHOMERUN_STATUS_COLOR_NEUTRAL; +- } +- +- if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) { +- ss_yellow_min = 50; /* -30dBmV */ +- ss_green_min = 75; /* -15dBmV */ +- } else { +- ss_yellow_min = 80; /* -12dBmV */ +- ss_green_min = 90; /* -6dBmV */ +- } +- +- if (status->signal_strength >= ss_green_min) { +- return HDHOMERUN_STATUS_COLOR_GREEN; +- } +- if (status->signal_strength >= ss_yellow_min) { +- return HDHOMERUN_STATUS_COLOR_YELLOW; +- } +- +- return HDHOMERUN_STATUS_COLOR_RED; +-} +- +-uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status) +-{ +- if (status->signal_to_noise_quality >= 70) { +- return HDHOMERUN_STATUS_COLOR_GREEN; +- } +- if (status->signal_to_noise_quality >= 50) { +- return HDHOMERUN_STATUS_COLOR_YELLOW; +- } +- +- return HDHOMERUN_STATUS_COLOR_RED; +-} +- +-uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status) +-{ +- if (status->symbol_error_quality >= 100) { +- return HDHOMERUN_STATUS_COLOR_GREEN; +- } +- +- return HDHOMERUN_STATUS_COLOR_RED; +-} +- +-int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status) ++int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status) + { + memset(status, 0, sizeof(struct hdhomerun_tuner_status_t)); + +@@ -374,18 +109,9 @@ + return ret; + } + +- if (pstatus_str) { +- *pstatus_str = status_str; +- } +- + char *channel = strstr(status_str, "ch="); + if (channel) { +- sscanf(channel + 3, "%31s", status->channel); +- } +- +- char *lock = strstr(status_str, "lock="); +- if (lock) { +- sscanf(lock + 5, "%31s", status->lock_str); ++ sscanf(channel + 3, "%s", status->channel); + } + + status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss="); +@@ -394,16 +120,6 @@ + status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps="); + status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps="); + +- status->signal_present = status->signal_strength >= 45; +- +- if (strcmp(status->lock_str, "none") != 0) { +- if (status->lock_str[0] == '(') { +- status->lock_unsupported = TRUE; +- } else { +- status->lock_supported = TRUE; +- } +- } +- + return 1; + } + +@@ -435,74 +151,26 @@ + return hdhomerun_control_get(hd->cs, name, pfilter, NULL); + } + +-int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram) ++int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number) + { + char name[32]; + sprintf(name, "/tuner%u/program", hd->tuner); +- return hdhomerun_control_get(hd->cs, name, pprogram, NULL); +-} +- +-int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget) +-{ +- char name[32]; +- sprintf(name, "/tuner%u/target", hd->tuner); +- return hdhomerun_control_get(hd->cs, name, ptarget, NULL); +-} +- +-int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount) +-{ +- char name[32]; +- sprintf(name, "/tuner%u/plotsample", hd->tuner); + +- char *result; +- int ret = hdhomerun_control_get(hd->cs, name, &result, NULL); ++ char *program_str; ++ int ret = hdhomerun_control_get(hd->cs, name, &program_str, NULL); + if (ret <= 0) { + return ret; + } + +- struct hdhomerun_plotsample_t *samples = (struct hdhomerun_plotsample_t *)result; +- *psamples = samples; +- size_t count = 0; +- +- while (1) { +- char *ptr = strchr(result, ' '); +- if (!ptr) { +- break; +- } +- *ptr++ = 0; +- +- unsigned long raw; +- if (sscanf(result, "%lx", &raw) != 1) { +- break; +- } +- +- uint16_t real = (raw >> 12) & 0x0FFF; +- if (real & 0x0800) { +- real |= 0xF000; +- } +- +- uint16_t imag = (raw >> 0) & 0x0FFF; +- if (imag & 0x0800) { +- imag |= 0xF000; +- } +- +- samples->real = (int16_t)real; +- samples->imag = (int16_t)imag; +- samples++; +- count++; +- +- result = ptr; +- } +- +- *pcount = count; ++ *pprogram_number = (uint16_t)atol(program_str); + return 1; + } + +-int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner) ++int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget) + { + char name[32]; +- sprintf(name, "/tuner%u/lockkey", hd->tuner); +- return hdhomerun_control_get(hd->cs, name, powner, NULL); ++ sprintf(name, "/tuner%u/target", hd->tuner); ++ return hdhomerun_control_get(hd->cs, name, ptarget, NULL); + } + + int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget) +@@ -510,11 +178,6 @@ + return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL); + } + +-int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation) +-{ +- return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL); +-} +- + int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num) + { + char *version_str; +@@ -543,119 +206,44 @@ + { + char name[32]; + sprintf(name, "/tuner%u/channel", hd->tuner); +- return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL); ++ return hdhomerun_control_set(hd->cs, name, channel, NULL, NULL); + } + + int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap) + { + char name[32]; + sprintf(name, "/tuner%u/channelmap", hd->tuner); +- return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL); ++ return hdhomerun_control_set(hd->cs, name, channelmap, NULL, NULL); + } + + int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter) + { + char name[32]; + sprintf(name, "/tuner%u/filter", hd->tuner); +- return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL); +-} +- +-static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end) +-{ +- char *ptr = *pptr; +- +- size_t available = end - ptr; +- size_t required; +- +- if (range_begin == range_end) { +- required = snprintf(ptr, available, "0x%04x ", range_begin) + 1; +- } else { +- required = snprintf(ptr, available, "0x%04x-0x%04x ", range_begin, range_end) + 1; +- } +- +- if (required > available) { +- return FALSE; +- } +- +- *pptr = strchr(ptr, 0); +- return TRUE; +-} +- +-int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]) +-{ +- char filter[1024]; +- char *ptr = filter; +- char *end = filter + sizeof(filter); +- +- uint16_t range_begin = 0xFFFF; +- uint16_t range_end = 0xFFFF; +- +- uint16_t i; +- for (i = 0; i <= 0x1FFF; i++) { +- if (!filter_array[i]) { +- if (range_begin == 0xFFFF) { +- continue; +- } +- if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) { +- return 0; +- } +- range_begin = 0xFFFF; +- range_end = 0xFFFF; +- continue; +- } +- +- if (range_begin == 0xFFFF) { +- range_begin = i; +- range_end = i; +- continue; +- } +- +- range_end = i; +- } +- +- if (range_begin != 0xFFFF) { +- if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) { +- return 0; +- } +- } +- +- /* Remove trailing space. */ +- if (ptr > filter) { +- ptr--; +- } +- *ptr = 0; +- +- return hdhomerun_device_set_tuner_filter(hd, filter); ++ return hdhomerun_control_set(hd->cs, name, filter, NULL, NULL); + } + +-int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program) ++int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number) + { +- char name[32]; ++ char name[32], value[32]; + sprintf(name, "/tuner%u/program", hd->tuner); +- return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL); ++ sprintf(value, "%u", program_number); ++ return hdhomerun_control_set(hd->cs, name, value, NULL, NULL); + } + +-int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target) ++int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target) + { + char name[32]; + sprintf(name, "/tuner%u/target", hd->tuner); +- return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL); ++ return hdhomerun_control_set(hd->cs, name, target, NULL, NULL); + } + +-int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol) ++static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd) + { +- /* Create video socket. */ +- hdhomerun_device_get_video_sock(hd); +- if (!hd->vs) { +- return -1; +- } +- +- /* Set target. */ + char target[64]; + uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs); + uint16_t local_port = hdhomerun_video_get_local_port(hd->vs); +- sprintf(target, "%s://%u.%u.%u.%u:%u", +- protocol, ++ sprintf(target, "%u.%u.%u.%u:%u", + (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF, + (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF, + (unsigned int)local_port +@@ -664,21 +252,11 @@ + return hdhomerun_device_set_tuner_target(hd, target); + } + +-int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd) +-{ +- return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); +-} +- + int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target) + { + return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL); + } + +-int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location) +-{ +- return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL); +-} +- + int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror) + { + return hdhomerun_control_get(hd->cs, name, pvalue, perror); +@@ -686,183 +264,41 @@ + + int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror) + { +- return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror); +-} +- +-int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror) +-{ +- uint32_t new_lockkey = (uint32_t)getcurrenttime(); +- +- char name[32]; +- sprintf(name, "/tuner%u/lockkey", hd->tuner); +- +- char new_lockkey_str[64]; +- sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey); +- +- int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, perror); +- if (ret <= 0) { +- hd->lockkey = 0; +- return ret; +- } +- +- hd->lockkey = new_lockkey; +- return ret; +-} +- +-int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd) +-{ +- if (hd->lockkey == 0) { +- return 1; +- } +- +- char name[32]; +- sprintf(name, "/tuner%u/lockkey", hd->tuner); +- int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL); +- +- hd->lockkey = 0; +- return ret; +-} +- +-int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd) +-{ +- char name[32]; +- sprintf(name, "/tuner%u/lockkey", hd->tuner); +- int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL); +- +- hd->lockkey = 0; +- return ret; +-} +- +-void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey) +-{ +- hd->lockkey = lockkey; ++ return hdhomerun_control_set(hd->cs, name, value, pvalue, perror); + } + +-int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status) ++int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd) + { +- /* Delay for SS reading to be valid (signal present). */ +- msleep(250); +- +- /* Wait for up to 2.5 seconds for lock. */ +- uint64_t timeout = getcurrenttime() + 2500; +- while (1) { +- /* Get status to check for lock. Quality numbers will not be valid yet. */ +- int ret = hdhomerun_device_get_tuner_status(hd, NULL, status); +- if (ret <= 0) { +- return ret; +- } +- +- if (!status->signal_present) { +- return 1; +- } +- if (status->lock_supported || status->lock_unsupported) { +- return 1; +- } +- +- if (getcurrenttime() >= timeout) { +- return 1; +- } +- +- msleep(250); ++ /* Create video socket. */ ++ hdhomerun_device_get_video_sock(hd); ++ if (!hd->vs) { ++ return -1; + } +-} + +-int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd) +-{ + /* Set target. */ +- int ret = hdhomerun_device_stream_refresh_target(hd); ++ int ret = hdhomerun_device_set_tuner_target_to_local(hd); + if (ret <= 0) { + return ret; + } + + /* Flush video buffer. */ +- msleep(64); ++ usleep(64000); + hdhomerun_video_flush(hd->vs); + + /* Success. */ + return 1; + } + +-int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd) +-{ +- int ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_RTP); +- if (ret == 0) { +- ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); +- } +- return ret; +-} +- + uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size) + { +- if (!hd->vs) { +- return NULL; +- } + return hdhomerun_video_recv(hd->vs, max_size, pactual_size); + } + +-void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd) +-{ +- hdhomerun_video_flush(hd->vs); +-} +- + void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd) + { + hdhomerun_device_set_tuner_target(hd, "none"); + } + +-int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap) +-{ +- if (hd->scan) { +- channelscan_destroy(hd->scan); +- } +- +- hd->scan = channelscan_create(hd, channelmap); +- if (!hd->scan) { +- return -1; +- } +- +- return 1; +-} +- +-int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) +-{ +- if (!hd->scan) { +- return 0; +- } +- +- int ret = channelscan_advance(hd->scan, result); +- if (ret <= 0) { +- channelscan_destroy(hd->scan); +- hd->scan = NULL; +- } +- +- return ret; +-} +- +-int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) +-{ +- if (!hd->scan) { +- return 0; +- } +- +- int ret = channelscan_detect(hd->scan, result); +- if (ret <= 0) { +- channelscan_destroy(hd->scan); +- hd->scan = NULL; +- } +- +- return ret; +-} +- +-uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd) +-{ +- if (!hd->scan) { +- return 0; +- } +- +- return channelscan_get_progress(hd->scan); +-} +- + int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features) + { + uint32_t version; +@@ -870,74 +306,16 @@ + return -1; + } + +- if (version < 20070219) { +- return 0; ++ if (version >= 20061213) { ++ return 1; + } + +- return 1; +-} +- +-const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd) +-{ +- if (*hd->model) { +- return hd->model; +- } +- +- char *model_str; +- int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL); +- if (ret < 0) { +- return NULL; +- } +- if (ret == 0) { +- model_str = "hdhomerun_atsc"; +- } +- +- strncpy(hd->model, model_str, sizeof(hd->model) - 1); +- hd->model[sizeof(hd->model) - 1] = 0; +- +- return hd->model; ++ return 0; + } + + int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file) + { +- hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL); + hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL); +- +- hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL); + hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL); +- + return hdhomerun_control_upgrade(hd->cs, upgrade_file); + } +- +-void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd) +-{ +- if (!hdhomerun_debug_enabled(hd->dbg)) { +- return; +- } +- +- char name[32]; +- sprintf(name, "/tuner%u/debug", hd->tuner); +- +- char *debug_str; +- char *error_str; +- int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str); +- if (ret < 0) { +- hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n"); +- return; +- } +- +- if (error_str) { +- hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str); +- } else { +- hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str); +- } +- +- if (hd->vs) { +- hdhomerun_video_debug_print_stats(hd->vs); +- } +-} +- +-void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats) +-{ +- hdhomerun_video_get_stats(hd->vs, stats); +-} +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_device.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_device.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_device.h + * +- * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,20 +14,8 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + #ifdef __cplusplus +@@ -38,8 +26,16 @@ + #define HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME 2000 + #define HDHOMERUN_DEVICE_MAX_TUNE_TO_DATA_TIME (HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME + HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME) + +-#define HDHOMERUN_TARGET_PROTOCOL_UDP "udp" +-#define HDHOMERUN_TARGET_PROTOCOL_RTP "rtp" ++struct hdhomerun_device_t; ++ ++struct hdhomerun_tuner_status_t { ++ char channel[32]; ++ unsigned int signal_strength; ++ unsigned int signal_to_noise_quality; ++ unsigned int symbol_error_quality; ++ uint32_t raw_bits_per_second; ++ uint32_t packets_per_second; ++}; + + /* + * Create a device object. +@@ -49,49 +45,22 @@ + * + * For example, a threaded application that streams video from 4 tuners (2 HDHomeRun devices) and has + * GUI feedback to the user of the selected tuner might use 5 device objects: 4 for streaming video +- * (one per thread) and one for the GUI display that can switch between tuners. ++ * (one per thread) and one for the GUI display that can just between tuners. + * +- * This function will not attempt to connect to the device. The connection will be established when first used. ++ * This function will not attempt to connect to the device. ++ * The connection will be established when first used. + * + * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. + * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. + * unsigned int tuner = tuner index (0 or 1). Can be changed later by calling hdhomerun_device_set_tuner. +- * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. + * + * Returns a pointer to the newly created device object. + * + * When no longer needed, the socket should be destroyed by calling hdhomerun_device_destroy. +- * +- * The hdhomerun_device_create_from_str function creates a device object from the given device_str. +- * The device_str parameter can be any of the following forms: +- * <device id> +- * <device id>-<tuner index> +- * <ip address> +- * If the tuner index is not included in the device_str then it is set to zero. Use hdhomerun_device_set_tuner +- * or hdhomerun_device_set_tuner_from_str to set the tuner. +- * +- * The hdhomerun_device_set_tuner_from_str function sets the tuner from the given tuner_str. +- * The tuner_str parameter can be any of the following forms: +- * <tuner index> +- * /tuner<tuner index> + */ +-extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg); +-extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg); +-extern LIBTYPE void hdhomerun_device_destroy(struct hdhomerun_device_t *hd); +- +-/* +- * Get the device id, ip, or tuner of the device instance. +- */ +-extern LIBTYPE const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd); +-extern LIBTYPE uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd); +-extern LIBTYPE uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd); +-extern LIBTYPE uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd); +-extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd); +-extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd); +- +-extern LIBTYPE void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip); +-extern LIBTYPE void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner); +-extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str); ++extern struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner); ++extern void hdhomerun_device_destroy(struct hdhomerun_device_t *hd); ++extern void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner); + + /* + * Get the local machine IP address used when communicating with the device. +@@ -100,7 +69,7 @@ + * + * Returns 32-bit IP address with native endianness, or 0 on error. + */ +-extern LIBTYPE uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd); ++extern uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd); + + /* + * Get operations. +@@ -113,24 +82,15 @@ + * Returns 0 if the operation was rejected. + * Returns -1 if a communication error occurred. + */ +-extern LIBTYPE int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status); +-extern LIBTYPE int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo); +-extern LIBTYPE int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel); +-extern LIBTYPE int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap); +-extern LIBTYPE int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter); +-extern LIBTYPE int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram); +-extern LIBTYPE int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget); +-extern LIBTYPE int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount); +-extern LIBTYPE int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner); +-extern LIBTYPE int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget); +-extern LIBTYPE int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation); +-extern LIBTYPE int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num); +- +-extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status); +-extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status); +-extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status); +- +-extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd); ++extern int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status); ++extern int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo); ++extern int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel); ++extern int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap); ++extern int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter); ++extern int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number); ++extern int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget); ++extern int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget); ++extern int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num); + + /* + * Set operations. +@@ -141,16 +101,12 @@ + * Returns 0 if the operation was rejected. + * Returns -1 if a communication error occurred. + */ +-extern LIBTYPE int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel); +-extern LIBTYPE int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap); +-extern LIBTYPE int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter); +-extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]); +-extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program); +-extern LIBTYPE int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target); +-extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol); +-extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd); +-extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target); +-extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location); ++extern int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel); ++extern int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap); ++extern int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter); ++extern int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number); ++extern int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target); ++extern int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target); + + /* + * Get/set a named control variable on the device. +@@ -169,42 +125,8 @@ + * Returns 0 if the operation was rejected (pvalue NULL, perror set). + * Returns -1 if a communication error occurs. + */ +-extern LIBTYPE int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror); +-extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror); +- +-/* +- * Tuner locking. +- * +- * The hdhomerun_device_tuner_lockkey_request function is used to obtain a lock +- * or to verify that the hdhomerun_device object still holds the lock. +- * Returns 1 if the lock request was successful and the lock was obtained. +- * Returns 0 if the lock request was rejected. +- * Returns -1 if a communication error occurs. +- * +- * The hdhomerun_device_tuner_lockkey_release function is used to release a +- * previously held lock. If locking is used then this function must be called +- * before destroying the hdhomerun_device object. +- */ +-extern LIBTYPE int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror); +-extern LIBTYPE int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd); +-extern LIBTYPE int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd); +- +-/* +- * Intended only for non persistent connections; eg, hdhomerun_config. +- */ +-extern LIBTYPE void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey); +- +-/* +- * Wait for tuner lock after channel change. +- * +- * The hdhomerun_device_wait_for_lock function is used to detect/wait for a lock vs no lock indication +- * after a channel change. +- * +- * It will return quickly if a lock is aquired. +- * It will return quickly if there is no signal detected. +- * Worst case it will time out after 1.5 seconds - the case where there is signal but no lock. +- */ +-extern LIBTYPE int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status); ++extern int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror); ++extern int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror); + + /* + * Stream a filtered program or the unfiltered stream. +@@ -222,19 +144,9 @@ + * + * The hdhomerun_device_stream_stop function tells the device to stop streaming data. + */ +-extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd); +-extern LIBTYPE int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd); +-extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size); +-extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd); +-extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd); +- +-/* +- * Channel scan API. +- */ +-extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap); +-extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result); +-extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result); +-extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd); ++extern int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd); ++extern uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size); ++extern void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd); + + /* + * Check that the device is running the recommended firmware. +@@ -245,7 +157,7 @@ + * Returns 0 if th firmware does not meet the minimum requriements for all operations. + * Returns -1 if an error occurs. + */ +-extern LIBTYPE int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features); ++extern int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features); + + /* + * Upload new firmware to the device. +@@ -256,19 +168,13 @@ + * Returns 0 if the upload was rejected. + * Returns -1 if an error occurs. + */ +-extern LIBTYPE int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file); ++extern int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file); + + /* + * Low level accessor functions. + */ +-extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd); +-extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd); +- +-/* +- * Debug print internal stats. +- */ +-extern LIBTYPE void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd); +-extern LIBTYPE void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats); ++extern struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd); ++extern struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd); + + #ifdef __cplusplus + } +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_device_selector.c +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_device_selector.h +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_dhcp.c +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_dhcp.h +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_discover.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_discover.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_discover.c + * +- * Copyright © 2006-2007 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,93 +14,206 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include "hdhomerun.h" ++#include "hdhomerun_os.h" ++#include "hdhomerun_pkt.h" ++#include "hdhomerun_discover.h" + + #if defined(__CYGWIN__) || defined(__WINDOWS__) + #include <windows.h> ++#include <iptypes.h> + #include <iphlpapi.h> +-#define USE_IPHLPAPI 1 +-#else +-#include <net/if.h> +-#include <sys/ioctl.h> +-#ifndef _SIZEOF_ADDR_IFREQ +-#define _SIZEOF_ADDR_IFREQ(x) sizeof(x) +-#endif + #endif + +-#define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16 ++// for OSX ++#include <unistd.h> // execl, pipe, sysconf ++#include <sys/types.h> // waitpid ++#include <sys/wait.h> // waitpid + + struct hdhomerun_discover_sock_t { + int sock; +- uint32_t local_ip; +- uint32_t subnet_mask; + }; + +-struct hdhomerun_discover_t { +- struct hdhomerun_discover_sock_t socks[HDHOMERUN_DISOCVER_MAX_SOCK_COUNT]; +- unsigned int sock_count; +- struct hdhomerun_pkt_t tx_pkt; +- struct hdhomerun_pkt_t rx_pkt; +-}; +- +-static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask) ++static struct hdhomerun_discover_sock_t *hdhomerun_discover_create(void) + { +- if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) { +- return FALSE; ++ struct hdhomerun_discover_sock_t *ds = (struct hdhomerun_discover_sock_t *)malloc(sizeof(struct hdhomerun_discover_sock_t)); ++ if (!ds) { ++ return NULL; + } +- ++ + /* Create socket. */ +- int sock = (int)socket(AF_INET, SOCK_DGRAM, 0); +- if (sock == -1) { +- return FALSE; ++ ds->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); ++ if (ds->sock == -1) { ++ free(ds); ++ return NULL; + } + + /* Set timeouts. */ +- setsocktimeout(sock, SOL_SOCKET, SO_SNDTIMEO, 1000); +- setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000); ++ setsocktimeout(ds->sock, SOL_SOCKET, SO_SNDTIMEO, 1000); ++ setsocktimeout(ds->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); + + /* Allow broadcast. */ + int sock_opt = 1; +- setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt)); ++ setsockopt(ds->sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt)); + + /* Bind socket. */ + struct sockaddr_in sock_addr; + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; +- sock_addr.sin_addr.s_addr = htonl(local_ip); ++ sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); + sock_addr.sin_port = htons(0); +- if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { +- close(sock); +- return FALSE; ++ if (bind(ds->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { ++ close(ds->sock); ++ free(ds); ++ return NULL; + } + +- /* Write sock entry. */ +- struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++]; +- dss->sock = sock; +- dss->local_ip = local_ip; +- dss->subnet_mask = subnet_mask; ++ /* Success. */ ++ return ds; ++} + +- return TRUE; ++static void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds) ++{ ++ close(ds->sock); ++ free(ds); + } + +-#if defined(USE_IPHLPAPI) +-static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds) ++static int hdhomerun_discover_send_packet(struct hdhomerun_discover_sock_t *ds, uint32_t ip_addr, uint32_t device_type, uint32_t device_id) ++{ ++ uint8_t buffer[1024]; ++ uint8_t *ptr = buffer; ++ hdhomerun_write_discover_request(&ptr, device_type, device_id); ++ ++ struct sockaddr_in sock_addr; ++ memset(&sock_addr, 0, sizeof(sock_addr)); ++ sock_addr.sin_family = AF_INET; ++ sock_addr.sin_addr.s_addr = htonl(ip_addr); ++ sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); ++ ++ int length = (int)(ptr - buffer); ++ if (sendto(ds->sock, (char *)buffer, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++#if defined(__APPLE__) ++static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, unsigned long device_type, unsigned long device_id) ++{ ++ /* printf("Looking for 0x%lx with id 0x%lx\n", device_type, device_id); */ ++ int fds[2]; ++ if (pipe(fds) < 0) ++ { ++ printf("Pipe Failed\n"); ++ return -1; ++ } ++ ++ pid_t child = fork(); ++ if (child < 0) ++ { ++ printf("Fork Failed\n"); ++ return -1; ++ } ++ else if (child == 0) ++ { ++ /* Child */ ++ int i = 0; ++ ++ /* Attach stdout to pipe */ ++ close(1); ++ dup2(fds[1], 1); ++ ++ /* Close all open file descriptors except stdout/stderr */ ++ for (i = sysconf(_SC_OPEN_MAX) - 1; i > 2; i--) ++ close(i); ++ ++ /* Run command */ ++ execl("/bin/sh", "sh", "-c", "ifconfig", NULL); ++ ++ /* Failed to exec */ ++ _exit(1); /* this exit is ok */ ++ } ++ else ++ { ++ /* Parent */ ++ int send_count = 0; ++ int status; ++ FILE *fp; ++ char line[1024]; ++ char adaptor[1024]; ++ ++ close(fds[1]); ++ ++ if (waitpid(child, &status, 0) < 0) ++ return -1; ++ ++ if (WEXITSTATUS(status)) ++ return -1; ++ ++ fp = fdopen(fds[0], "r"); ++ while (1) ++ { ++ char *ptr = NULL; ++ int netmask, broadcast; ++ int a,b,c,d; ++ ++ if (!fgets(line, sizeof(line) - 1, fp)) ++ { ++ break; ++ } ++ ++ line[1023] = 0; ++ ++ /* find ": flags" */ ++ ptr = strnstr(line, ": flags", 1024 - 1); ++ if (ptr >= line) ++ { ++ /* grab adaptor before that */ ++ strncpy(adaptor, line, ptr-line); ++ adaptor[ptr-line] = 0; ++ } ++ ++ /* find "netmask " */ ++ ptr = strnstr(line, "netmask ", 1024 - 1); ++ if (ptr <= line) ++ continue; ++ ptr += strlen("netmask "); ++ sscanf(ptr, "%x", &netmask); ++ ++ /* find "broadcast " */ ++ ptr = strnstr(ptr, "broadcast ", 1024 - 1); ++ if (ptr <= line) ++ continue; ++ ptr += strlen("broadcast "); ++ sscanf(ptr, "%i.%i.%i.%i", &a, &b, &c, &d); ++ broadcast = a<<24 | b<<16 | c<<8 | d; ++ /* ++ printf("Adaptor: '%s' 0x%08x %i.%i.%i.%i\n", ++ adaptor, broadcast, a,b,c,d); ++ */ ++ ++ /* send discover packet this adaptor */ ++ if (hdhomerun_discover_send_packet( ++ ds, broadcast, device_type, device_id) >= 0) ++ { ++ send_count++; ++ } ++ } ++ ++ fclose(fp); /* this closes fds[0] as well */ ++ ++ /* printf("send_count: %i\n\n", send_count); */ ++ return (send_count == 0) ? -1 : 0; ++ } ++} ++ ++#elif defined(__CYGWIN__) || defined(__WINDOWS__) ++ ++static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) + { + PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); + ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); +@@ -109,29 +222,37 @@ + if (Ret != NO_ERROR) { + free(pAdapterInfo); + if (Ret != ERROR_BUFFER_OVERFLOW) { +- return; ++ return -1; + } + pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); + Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); + if (Ret != NO_ERROR) { + free(pAdapterInfo); +- return; ++ return -1; + } + } + ++ unsigned int send_count = 0; + PIP_ADAPTER_INFO pAdapter = pAdapterInfo; + while (pAdapter) { + IP_ADDR_STRING *pIPAddr = &pAdapter->IpAddressList; + while (pIPAddr) { +- uint32_t local_ip = ntohl(inet_addr(pIPAddr->IpAddress.String)); ++ uint32_t addr = ntohl(inet_addr(pIPAddr->IpAddress.String)); + uint32_t mask = ntohl(inet_addr(pIPAddr->IpMask.String)); ++ ++ uint32_t broadcast = addr | ~mask; ++ if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) { ++ pIPAddr = pIPAddr->Next; ++ continue; ++ } + +- if (local_ip == 0) { ++ if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) { + pIPAddr = pIPAddr->Next; + continue; + } + +- hdhomerun_discover_sock_create(ds, local_ip, mask); ++ send_count++; ++ + pIPAddr = pIPAddr->Next; + } + +@@ -139,198 +260,111 @@ + } + + free(pAdapterInfo); +-} +- +-#else + +-static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds) +-{ +- int fd = socket(AF_INET, SOCK_DGRAM, 0); +- if (fd == -1) { +- return; ++ if (send_count == 0) { ++ return -1; + } ++ return 0; ++} + +- struct ifconf ifc; +- uint8_t buf[8192]; +- ifc.ifc_len = sizeof(buf); +- ifc.ifc_buf = (char *)buf; +- +- memset(buf, 0, sizeof(buf)); ++#elif defined(__linux__) + +- if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { +- close(fd); +- return; ++static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) ++{ ++ FILE *fp = fopen("/proc/net/route", "r"); ++ if (!fp) { ++ return -1; + } + +- uint8_t *ptr = (uint8_t *)ifc.ifc_req; +- uint8_t *end = (uint8_t *)&ifc.ifc_buf[ifc.ifc_len]; +- +- while (ptr <= end) { +- struct ifreq *ifr = (struct ifreq *)ptr; +- ptr += _SIZEOF_ADDR_IFREQ(*ifr); ++ unsigned int send_count = 0; ++ while (1) { ++ char line[256]; ++ if (!fgets(line, sizeof(line), fp)) { ++ break; ++ } ++ line[255] = 0; + +- if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { ++ uint32_t dest; ++ uint32_t mask; ++ if (sscanf(line, "%*s %x %*x %*x %*d %*d %*d %x", &dest, &mask) != 2) { + continue; + } +- struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr); +- uint32_t local_ip = ntohl(addr_in->sin_addr.s_addr); +- if (local_ip == 0) { ++ dest = ntohl(dest); ++ mask = ntohl(mask); ++ ++ uint32_t broadcast = dest | ~mask; ++ ++ if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) { + continue; + } + +- if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { ++ if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) { + continue; + } +- struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr); +- uint32_t mask = ntohl(mask_in->sin_addr.s_addr); + +- hdhomerun_discover_sock_create(ds, local_ip, mask); ++ send_count++; + } +-} +-#endif + +-static struct hdhomerun_discover_t *hdhomerun_discover_create(void) +-{ +- struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t)); +- if (!ds) { +- return NULL; +- } +- +- /* Create a routable socket. */ +- if (!hdhomerun_discover_sock_create(ds, 0, 0)) { +- free(ds); +- return NULL; ++ fclose(fp); ++ if (send_count == 0) { ++ return -1; + } +- +- /* Detect & create local sockets. */ +- hdhomerun_discover_sock_detect(ds); +- +- /* Success. */ +- return ds; ++ return 0; + } + +-static void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds) +-{ +- unsigned int i; +- for (i = 0; i < ds->sock_count; i++) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; +- close(dss->sock); +- } +- +- free(ds); +-} ++#else + +-static bool_t hdhomerun_discover_send_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, uint32_t target_ip, uint32_t device_type, uint32_t device_id) ++static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) + { +- struct hdhomerun_pkt_t *tx_pkt = &ds->tx_pkt; +- hdhomerun_pkt_reset(tx_pkt); +- +- hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_TYPE); +- hdhomerun_pkt_write_var_length(tx_pkt, 4); +- hdhomerun_pkt_write_u32(tx_pkt, device_type); +- hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_ID); +- hdhomerun_pkt_write_var_length(tx_pkt, 4); +- hdhomerun_pkt_write_u32(tx_pkt, device_id); +- hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ); +- +- struct sockaddr_in sock_addr; +- memset(&sock_addr, 0, sizeof(sock_addr)); +- sock_addr.sin_family = AF_INET; +- sock_addr.sin_addr.s_addr = htonl(target_ip); +- sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); +- +- int length = (int)(tx_pkt->end - tx_pkt->start); +- if (sendto(dss->sock, (char *)tx_pkt->start, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) { +- return FALSE; +- } +- +- return TRUE; ++ return -1; + } ++#endif + +-static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id) ++static int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) + { +- bool_t result = FALSE; +- +- /* +- * Send subnet broadcast using each local ip socket. +- * This will work with multiple separate 169.254.x.x interfaces. +- */ +- unsigned int i; +- for (i = 1; i < ds->sock_count; i++) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; +- uint32_t target_ip = dss->local_ip | ~dss->subnet_mask; +- result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); +- } +- +- /* +- * If no local ip sockets then fall back to sending a global broadcast letting the OS choose the interface. +- */ +- if (!result) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[0]; +- result = hdhomerun_discover_send_internal(ds, dss, 0xFFFFFFFF, device_type, device_id); ++ if (hdhomerun_discover_send_internal(ds, device_type, device_id) < 0) { ++ return hdhomerun_discover_send_packet(ds, 0xFFFFFFFF, device_type, device_id); + } +- +- return result; ++ return 0; + } + +-static bool_t hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id) ++static int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result) + { +- bool_t result = FALSE; +- +- /* +- * Send targeted packet from any local ip that is in the same subnet. +- * This will work with multiple separate 169.254.x.x interfaces. +- */ +- unsigned int i; +- for (i = 1; i < ds->sock_count; i++) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; +- if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) { +- continue; +- } ++ struct timeval t; ++ t.tv_sec = 0; ++ t.tv_usec = 250000; + +- result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); +- } ++ fd_set readfds; ++ FD_ZERO(&readfds); ++ FD_SET(ds->sock, &readfds); + +- /* +- * If target IP does not match a local subnet then fall back to letting the OS choose the gateway interface. +- */ +- if (!result) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[0]; +- result = hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); ++ if (select(ds->sock+1, &readfds, NULL, NULL, &t) < 0) { ++ return -1; + } +- +- return result; +-} +- +-static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id) +-{ +- if (target_ip != 0) { +- return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id); ++ if (!FD_ISSET(ds->sock, &readfds)) { ++ return 0; + } + +- return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id); +-} +- +-static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result) +-{ +- struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt; +- hdhomerun_pkt_reset(rx_pkt); +- ++ uint8_t buffer[1024]; + struct sockaddr_in sock_addr; +- memset(&sock_addr, 0, sizeof(sock_addr)); + socklen_t sockaddr_size = sizeof(sock_addr); +- +- int rx_length = recvfrom(dss->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); ++ int rx_length = recvfrom(ds->sock, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); + if (rx_length <= 0) { + /* Don't return error - windows machine on VPN can sometimes cause a sock error here but otherwise works. */ + return 0; + } +- rx_pkt->end += rx_length; ++ if (rx_length < HDHOMERUN_MIN_PEEK_LENGTH) { ++ return 0; ++ } + +- uint16_t type; +- if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) { ++ size_t length = hdhomerun_peek_packet_length(buffer); ++ if (length > (size_t)rx_length) { + return 0; + } ++ ++ uint8_t *ptr = buffer; ++ uint8_t *end = buffer + length; ++ int type = hdhomerun_process_packet(&ptr, &end); + if (type != HDHOMERUN_TYPE_DISCOVER_RPY) { + return 0; + } +@@ -338,12 +372,11 @@ + result->ip_addr = ntohl(sock_addr.sin_addr.s_addr); + result->device_type = 0; + result->device_id = 0; +- + while (1) { + uint8_t tag; + size_t len; +- uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); +- if (!next) { ++ uint8_t *value; ++ if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &value) < 0) { + break; + } + +@@ -352,71 +385,28 @@ + if (len != 4) { + break; + } +- result->device_type = hdhomerun_pkt_read_u32(rx_pkt); ++ result->device_type = hdhomerun_read_u32(&value); + break; +- + case HDHOMERUN_TAG_DEVICE_ID: + if (len != 4) { + break; + } +- result->device_id = hdhomerun_pkt_read_u32(rx_pkt); ++ result->device_id = hdhomerun_read_u32(&value); + break; +- + default: + break; + } +- +- rx_pkt->pos = next; + } + + return 1; + } + +-static int hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result) +-{ +- struct timeval t; +- t.tv_sec = 0; +- t.tv_usec = 250000; +- +- fd_set readfds; +- FD_ZERO(&readfds); +- int max_sock = -1; +- +- unsigned int i; +- for (i = 0; i < ds->sock_count; i++) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; +- FD_SET(dss->sock, &readfds); +- if (dss->sock > max_sock) { +- max_sock = dss->sock; +- } +- } +- +- if (select(max_sock+1, &readfds, NULL, NULL, &t) < 0) { +- return -1; +- } +- +- for (i = 0; i < ds->sock_count; i++) { +- struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; +- if (!FD_ISSET(dss->sock, &readfds)) { +- continue; +- } +- +- if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) { +- continue; +- } +- +- return 1; +- } +- +- return 0; +-} +- +-static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t ip_addr) ++static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t device_id) + { + int index; + for (index = 0; index < count; index++) { + struct hdhomerun_discover_device_t *result = &result_list[index]; +- if (result->ip_addr == ip_addr) { ++ if (result->device_id == device_id) { + return result; + } + } +@@ -424,12 +414,13 @@ + return NULL; + } + +-static int hdhomerun_discover_find_devices_internal(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count) ++static int hdhomerun_discover_find_devices_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count) + { + int count = 0; ++ + int attempt; + for (attempt = 0; attempt < 4; attempt++) { +- if (!hdhomerun_discover_send(ds, target_ip, device_type, device_id)) { ++ if (hdhomerun_discover_send(ds, device_type, device_id) < 0) { + return -1; + } + +@@ -442,7 +433,7 @@ + return -1; + } + if (ret == 0) { +- continue; ++ break; + } + + /* Filter. */ +@@ -458,7 +449,7 @@ + } + + /* Ensure not already in list. */ +- if (hdhomerun_discover_find_in_list(result_list, count, result->ip_addr)) { ++ if (hdhomerun_discover_find_in_list(result_list, count, result->device_id)) { + continue; + } + +@@ -473,14 +464,27 @@ + return count; + } + +-int hdhomerun_discover_find_devices_custom(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count) ++int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result) ++{ ++ struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create(); ++ if (!ds) { ++ return -1; ++ } ++ ++ int ret = hdhomerun_discover_find_devices_internal(ds, HDHOMERUN_DEVICE_TYPE_WILDCARD, device_id, result, 1); ++ ++ hdhomerun_discover_destroy(ds); ++ return ret; ++} ++ ++int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count) + { +- struct hdhomerun_discover_t *ds = hdhomerun_discover_create(); ++ struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create(); + if (!ds) { + return -1; + } + +- int ret = hdhomerun_discover_find_devices_internal(ds, target_ip, device_type, device_id, result_list, max_count); ++ int ret = hdhomerun_discover_find_devices_internal(ds, device_type, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, max_count); + + hdhomerun_discover_destroy(ds); + return ret; +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_discover.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_discover.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_discover.h + * +- * Copyright © 2006-2007 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,20 +14,8 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifdef __cplusplus + extern "C" { +@@ -40,18 +28,29 @@ + }; + + /* +- * Find devices. ++ * Find a device by device ID. ++ * ++ * The device information is stored in caller-supplied hdhomerun_discover_device_t var. ++ * Multiple attempts are made to find the device. ++ * Worst-case execution time is 1 second. ++ * ++ * Returns 1 on success. ++ * Returns 0 if not found. ++ * Retruns -1 on error. ++ */ ++extern int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result); ++ ++/* ++ * Find all devices of a given type. + * + * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars. + * Multiple attempts are made to find devices. + * Execution time is 1 second. + * +- * Set target_ip to zero to auto-detect IP address. +- * + * Returns the number of devices found. + * Retruns -1 on error. + */ +-extern LIBTYPE int hdhomerun_discover_find_devices_custom(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count); ++extern int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count); + + /* + * Verify that the device ID given is valid. +@@ -62,7 +61,7 @@ + * Returns TRUE if valid. + * Returns FALSE if not valid. + */ +-extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id); ++extern bool_t hdhomerun_discover_validate_device_id(uint32_t device_id); + + #ifdef __cplusplus + } +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_os.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_os.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_os.h + * +- * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,36 +14,97 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#if defined(_WIN32) || defined(_WIN64) ++#include <stdlib.h> ++#include <stdio.h> ++#include <string.h> ++ ++#if defined(WIN32) + #define __WINDOWS__ + #endif + + #if defined(__WINDOWS__) +-#include "hdhomerun_os_windows.h" ++#include <windows.h> ++#include <sys/types.h> ++#include <sys/timeb.h> + #else +-#include "hdhomerun_os_posix.h" ++#include <unistd.h> ++#include <errno.h> ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <arpa/inet.h> ++#include <netdb.h> ++#include <sys/time.h> ++#include <sys/timeb.h> ++#include <fcntl.h> + #endif + ++#include <pthread.h> ++ + #if !defined(TRUE) + #define TRUE 1 + #endif +- + #if !defined(FALSE) + #define FALSE 0 + #endif ++ ++#if defined(__WINDOWS__) ++ ++typedef int bool_t; ++typedef unsigned __int8 uint8_t; ++typedef unsigned __int16 uint16_t; ++typedef unsigned __int32 uint32_t; ++typedef unsigned __int64 uint64_t; ++ ++#define socklen_t int ++#define close closesocket ++#define sock_getlasterror WSAGetLastError() ++#define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT) ++#define atoll _atoi64 ++#define strcasecmp _stricmp ++#define fseeko _fseeki64 ++#define ftello _ftelli64 ++#define usleep(us) Sleep((us)/1000) ++#define sleep(sec) Sleep((sec)*1000) ++ ++static inline uint64_t getcurrenttime(void) ++{ ++ struct timeb tb; ++ ftime(&tb); ++ return ((uint64_t)tb.time * 1000) + tb.millitm; ++} ++ ++static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout) ++{ ++ int t = (int)timeout; ++ return setsockopt(s, level, optname, (char *)&t, sizeof(t)); ++} ++ ++#else ++ ++typedef int bool_t; ++ ++#define sock_getlasterror errno ++#define sock_getlasterror_socktimeout (errno == EAGAIN) ++ ++static inline uint64_t getcurrenttime(void) ++{ ++ struct timeval t; ++ gettimeofday(&t, NULL); ++ return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000); ++} ++ ++static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout) ++{ ++ struct timeval t; ++ t.tv_sec = timeout / 1000; ++ t.tv_usec = (timeout % 1000) * 1000; ++ return setsockopt(s, level, optname, (char *)&t, sizeof(t)); ++} ++ ++#endif ++ +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_os_posix.h +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_os_windows.h +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_pkt.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_pkt.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_pkt.c + * +- * Copyright © 2005-2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,232 +14,255 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include "hdhomerun.h" ++#include "hdhomerun_os.h" ++#include "hdhomerun_pkt.h" + +-struct hdhomerun_pkt_t *hdhomerun_pkt_create(void) ++uint8_t hdhomerun_read_u8(uint8_t **pptr) + { +- struct hdhomerun_pkt_t *pkt = (struct hdhomerun_pkt_t *)calloc(1, sizeof(struct hdhomerun_pkt_t)); +- if (!pkt) { +- return NULL; +- } +- +- hdhomerun_pkt_reset(pkt); +- +- return pkt; +-} +- +-void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt) +-{ +- free(pkt); +-} +- +-void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt) +-{ +- pkt->limit = pkt->buffer + sizeof(pkt->buffer) - 4; +- pkt->start = pkt->buffer + 1024; +- pkt->end = pkt->start; +- pkt->pos = pkt->start; +-} +- +-static uint32_t hdhomerun_pkt_calc_crc(uint8_t *start, uint8_t *end) +-{ +- uint8_t *pos = start; +- uint32_t crc = 0xFFFFFFFF; +- while (pos < end) { +- uint8_t x = (uint8_t)(crc) ^ *pos++; +- crc >>= 8; +- if (x & 0x01) crc ^= 0x77073096; +- if (x & 0x02) crc ^= 0xEE0E612C; +- if (x & 0x04) crc ^= 0x076DC419; +- if (x & 0x08) crc ^= 0x0EDB8832; +- if (x & 0x10) crc ^= 0x1DB71064; +- if (x & 0x20) crc ^= 0x3B6E20C8; +- if (x & 0x40) crc ^= 0x76DC4190; +- if (x & 0x80) crc ^= 0xEDB88320; +- } +- return crc ^ 0xFFFFFFFF; +-} +- +-uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt) +-{ +- uint8_t v = *pkt->pos++; ++ uint8_t *ptr = *pptr; ++ uint8_t v = *ptr++; ++ *pptr = ptr; + return v; + } + +-uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt) ++uint16_t hdhomerun_read_u16(uint8_t **pptr) + { ++ uint8_t *ptr = *pptr; + uint16_t v; +- v = (uint16_t)*pkt->pos++ << 8; +- v |= (uint16_t)*pkt->pos++ << 0; ++ v = (uint16_t)*ptr++ << 8; ++ v |= (uint16_t)*ptr++ << 0; ++ *pptr = ptr; + return v; + } + +-uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt) ++uint32_t hdhomerun_read_u32(uint8_t **pptr) + { ++ uint8_t *ptr = *pptr; + uint32_t v; +- v = (uint32_t)*pkt->pos++ << 24; +- v |= (uint32_t)*pkt->pos++ << 16; +- v |= (uint32_t)*pkt->pos++ << 8; +- v |= (uint32_t)*pkt->pos++ << 0; ++ v = (uint32_t)*ptr++ << 24; ++ v |= (uint32_t)*ptr++ << 16; ++ v |= (uint32_t)*ptr++ << 8; ++ v |= (uint32_t)*ptr++ << 0; ++ *pptr = ptr; + return v; + } + +-size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt) ++size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end) + { ++ uint8_t *ptr = *pptr; + size_t length; + +- if (pkt->pos + 1 > pkt->end) { +- return (size_t)-1; ++ if (ptr + 1 > end) { ++ return -1; + } + +- length = (size_t)*pkt->pos++; ++ length = (size_t)*ptr++; + if (length & 0x0080) { +- if (pkt->pos + 1 > pkt->end) { +- return (size_t)-1; ++ if (ptr + 1 > end) { ++ return -1; + } + + length &= 0x007F; +- length |= (size_t)*pkt->pos++ << 7; ++ length |= (size_t)*ptr++ << 7; + } + ++ *pptr = ptr; + return length; + } + +-uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength) ++int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue) + { +- if (pkt->pos + 2 > pkt->end) { +- return NULL; ++ if (end - *pptr < 2) { ++ return -1; + } + +- *ptag = hdhomerun_pkt_read_u8(pkt); +- *plength = hdhomerun_pkt_read_var_length(pkt); +- +- if (pkt->pos + *plength > pkt->end) { +- return NULL; ++ *ptag = hdhomerun_read_u8(pptr); ++ *plength = hdhomerun_read_var_length(pptr, end); ++ *pvalue = *pptr; ++ ++ if ((size_t)(end - *pptr) < *plength) { ++ return -1; + } + +- return pkt->pos + *plength; ++ *pptr += *plength; ++ return 0; + } + +-void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v) ++void hdhomerun_write_u8(uint8_t **pptr, uint8_t v) + { +- *pkt->pos++ = v; ++ uint8_t *ptr = *pptr; ++ *ptr++ = v; ++ *pptr = ptr; ++} + +- if (pkt->pos > pkt->end) { +- pkt->end = pkt->pos; +- } ++void hdhomerun_write_u16(uint8_t **pptr, uint16_t v) ++{ ++ uint8_t *ptr = *pptr; ++ *ptr++ = (uint8_t)(v >> 8); ++ *ptr++ = (uint8_t)(v >> 0); ++ *pptr = ptr; + } + +-void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v) ++void hdhomerun_write_u32(uint8_t **pptr, uint32_t v) + { +- *pkt->pos++ = (uint8_t)(v >> 8); +- *pkt->pos++ = (uint8_t)(v >> 0); ++ uint8_t *ptr = *pptr; ++ *ptr++ = (uint8_t)(v >> 24); ++ *ptr++ = (uint8_t)(v >> 16); ++ *ptr++ = (uint8_t)(v >> 8); ++ *ptr++ = (uint8_t)(v >> 0); ++ *pptr = ptr; ++} + +- if (pkt->pos > pkt->end) { +- pkt->end = pkt->pos; ++void hdhomerun_write_var_length(uint8_t **pptr, size_t v) ++{ ++ uint8_t *ptr = *pptr; ++ if (v <= 127) { ++ *ptr++ = (uint8_t)v; ++ } else { ++ *ptr++ = (uint8_t)(v | 0x80); ++ *ptr++ = (uint8_t)(v >> 7); + } ++ *pptr = ptr; + } + +-void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v) ++static void hdhomerun_write_mem(uint8_t **pptr, void *mem, size_t length) + { +- *pkt->pos++ = (uint8_t)(v >> 24); +- *pkt->pos++ = (uint8_t)(v >> 16); +- *pkt->pos++ = (uint8_t)(v >> 8); +- *pkt->pos++ = (uint8_t)(v >> 0); ++ uint8_t *ptr = *pptr; ++ memcpy(ptr, mem, length); ++ ptr += length; ++ *pptr = ptr; ++} + +- if (pkt->pos > pkt->end) { +- pkt->end = pkt->pos; ++static uint32_t hdhomerun_calc_crc(uint8_t *start, uint8_t *end) ++{ ++ uint8_t *ptr = start; ++ uint32_t crc = 0xFFFFFFFF; ++ while (ptr < end) { ++ uint8_t x = (uint8_t)(crc) ^ *ptr++; ++ crc >>= 8; ++ if (x & 0x01) crc ^= 0x77073096; ++ if (x & 0x02) crc ^= 0xEE0E612C; ++ if (x & 0x04) crc ^= 0x076DC419; ++ if (x & 0x08) crc ^= 0x0EDB8832; ++ if (x & 0x10) crc ^= 0x1DB71064; ++ if (x & 0x20) crc ^= 0x3B6E20C8; ++ if (x & 0x40) crc ^= 0x76DC4190; ++ if (x & 0x80) crc ^= 0xEDB88320; + } ++ return crc ^ 0xFFFFFFFF; + } + +-void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v) ++static int hdhomerun_check_crc(uint8_t *start, uint8_t *end) + { +- if (v <= 127) { +- *pkt->pos++ = (uint8_t)v; +- } else { +- *pkt->pos++ = (uint8_t)(v | 0x80); +- *pkt->pos++ = (uint8_t)(v >> 7); ++ if (end - start < 8) { ++ return -1; + } +- +- if (pkt->pos > pkt->end) { +- pkt->end = pkt->pos; ++ uint8_t *ptr = end -= 4; ++ uint32_t actual_crc = hdhomerun_calc_crc(start, ptr); ++ uint32_t packet_crc; ++ packet_crc = (uint32_t)*ptr++ << 0; ++ packet_crc |= (uint32_t)*ptr++ << 8; ++ packet_crc |= (uint32_t)*ptr++ << 16; ++ packet_crc |= (uint32_t)*ptr++ << 24; ++ if (actual_crc != packet_crc) { ++ return -1; + } ++ return 0; + } + +-void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length) ++static void hdhomerun_write_header_length(uint8_t *ptr, size_t length) + { +- memcpy(pkt->pos, mem, length); +- pkt->pos += length; ++ hdhomerun_write_u16(&ptr, (uint16_t)length); ++} + +- if (pkt->pos > pkt->end) { +- pkt->end = pkt->pos; +- } ++void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start) ++{ ++ uint8_t *ptr = *pptr; ++ uint32_t crc = hdhomerun_calc_crc(start, ptr); ++ *ptr++ = (uint8_t)(crc >> 0); ++ *ptr++ = (uint8_t)(crc >> 8); ++ *ptr++ = (uint8_t)(crc >> 16); ++ *ptr++ = (uint8_t)(crc >> 24); ++ *pptr = ptr; + } + +-int hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype) ++void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id) + { +- pkt->pos = pkt->start; ++ uint8_t *start = *pptr; ++ hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_DISCOVER_REQ); ++ hdhomerun_write_u16(pptr, 0); + +- if (pkt->pos + 4 > pkt->end) { +- return 0; +- } ++ hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_TYPE); ++ hdhomerun_write_var_length(pptr, 4); ++ hdhomerun_write_u32(pptr, device_type); ++ hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_ID); ++ hdhomerun_write_var_length(pptr, 4); ++ hdhomerun_write_u32(pptr, device_id); + +- *ptype = hdhomerun_pkt_read_u16(pkt); +- size_t length = hdhomerun_pkt_read_u16(pkt); +- pkt->pos += length; ++ hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4)); ++ hdhomerun_write_crc(pptr, start); ++} + +- if (pkt->pos + 4 > pkt->end) { +- pkt->pos = pkt->start; +- return 0; +- } ++void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value) ++{ ++ uint8_t *start = *pptr; ++ hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_GETSET_REQ); ++ hdhomerun_write_u16(pptr, 0); + +- uint32_t calc_crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->pos); ++ int name_len = (int)strlen(name) + 1; ++ hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_NAME); ++ hdhomerun_write_var_length(pptr, name_len); ++ hdhomerun_write_mem(pptr, (void *)name, name_len); + +- uint32_t packet_crc; +- packet_crc = (uint32_t)*pkt->pos++ << 0; +- packet_crc |= (uint32_t)*pkt->pos++ << 8; +- packet_crc |= (uint32_t)*pkt->pos++ << 16; +- packet_crc |= (uint32_t)*pkt->pos++ << 24; +- if (calc_crc != packet_crc) { +- return -1; ++ if (value) { ++ int value_len = (int)strlen(value) + 1; ++ hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_VALUE); ++ hdhomerun_write_var_length(pptr, value_len); ++ hdhomerun_write_mem(pptr, (void *)value, value_len); + } + +- pkt->start += 4; +- pkt->end = pkt->start + length; +- pkt->pos = pkt->start; +- return 1; ++ hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4)); ++ hdhomerun_write_crc(pptr, start); + } + +-void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type) ++void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length) + { +- size_t length = pkt->end - pkt->start; ++ uint8_t *start = *pptr; ++ hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_UPGRADE_REQ); ++ hdhomerun_write_u16(pptr, 0); + +- pkt->start -= 4; +- pkt->pos = pkt->start; +- hdhomerun_pkt_write_u16(pkt, frame_type); +- hdhomerun_pkt_write_u16(pkt, (uint16_t)length); ++ hdhomerun_write_u32(pptr, sequence); ++ if (length > 0) { ++ hdhomerun_write_mem(pptr, data, length); ++ } + +- uint32_t crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->end); +- *pkt->end++ = (uint8_t)(crc >> 0); +- *pkt->end++ = (uint8_t)(crc >> 8); +- *pkt->end++ = (uint8_t)(crc >> 16); +- *pkt->end++ = (uint8_t)(crc >> 24); ++ hdhomerun_write_header_length(start + 2, *pptr - start - 4); ++ hdhomerun_write_crc(pptr, start); ++} + +- pkt->pos = pkt->start; ++size_t hdhomerun_peek_packet_length(uint8_t *ptr) ++{ ++ ptr += 2; ++ return (size_t)hdhomerun_read_u16(&ptr) + 8; + } ++ ++int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend) ++{ ++ if (hdhomerun_check_crc(*pptr, *pend) < 0) { ++ return -1; ++ } ++ *pend -= 4; ++ ++ uint16_t type = hdhomerun_read_u16(pptr); ++ uint16_t length = hdhomerun_read_u16(pptr); ++ if ((*pend - *pptr) < length) { ++ return -1; ++ } ++ *pend = *pptr + length; ++ return (int)type; ++} ++ +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_pkt.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_pkt.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_pkt.h + * +- * Copyright © 2005-2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,20 +14,8 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifdef __cplusplus + extern "C" { +@@ -122,9 +110,6 @@ + #define HDHOMERUN_DISCOVER_UDP_PORT 65001 + #define HDHOMERUN_CONTROL_TCP_PORT 65001 + +-#define HDHOMERUN_MAX_PACKET_SIZE 1460 +-#define HDHOMERUN_MAX_PAYLOAD_SIZE 1452 +- + #define HDHOMERUN_TYPE_DISCOVER_REQ 0x0002 + #define HDHOMERUN_TYPE_DISCOVER_RPY 0x0003 + #define HDHOMERUN_TYPE_GETSET_REQ 0x0004 +@@ -136,7 +121,6 @@ + #define HDHOMERUN_TAG_DEVICE_ID 0x02 + #define HDHOMERUN_TAG_GETSET_NAME 0x03 + #define HDHOMERUN_TAG_GETSET_VALUE 0x04 +-#define HDHOMERUN_TAG_GETSET_LOCKKEY 0x15 + #define HDHOMERUN_TAG_ERROR_MESSAGE 0x05 + + #define HDHOMERUN_DEVICE_TYPE_WILDCARD 0xFFFFFFFF +@@ -145,33 +129,25 @@ + + #define HDHOMERUN_MIN_PEEK_LENGTH 4 + +-struct hdhomerun_pkt_t { +- uint8_t *pos; +- uint8_t *start; +- uint8_t *end; +- uint8_t *limit; +- uint8_t buffer[3074]; +-}; +- +-extern LIBTYPE struct hdhomerun_pkt_t *hdhomerun_pkt_create(void); +-extern LIBTYPE void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt); +-extern LIBTYPE void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt); +- +-extern LIBTYPE uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt); +-extern LIBTYPE uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt); +-extern LIBTYPE uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt); +-extern LIBTYPE size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt); +-extern LIBTYPE uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength); +- +-extern LIBTYPE void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v); +-extern LIBTYPE void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v); +-extern LIBTYPE void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v); +-extern LIBTYPE void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v); +-extern LIBTYPE void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length); +- +-extern LIBTYPE bool_t hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype); +-extern LIBTYPE void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type); ++extern uint8_t hdhomerun_read_u8(uint8_t **pptr); ++extern uint16_t hdhomerun_read_u16(uint8_t **pptr); ++extern uint32_t hdhomerun_read_u32(uint8_t **pptr); ++extern size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end); ++extern void hdhomerun_write_u8(uint8_t **pptr, uint8_t v); ++extern void hdhomerun_write_u16(uint8_t **pptr, uint16_t v); ++extern void hdhomerun_write_u32(uint8_t **pptr, uint32_t v); ++extern void hdhomerun_write_var_length(uint8_t **pptr, size_t v); ++extern void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start); ++ ++extern size_t hdhomerun_peek_packet_length(uint8_t *ptr); ++extern int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend); ++extern int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue); ++ ++extern void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id); ++extern void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value); ++extern void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length); + + #ifdef __cplusplus + } + #endif ++ +Only in branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun: hdhomerun_types.h +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.c src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_video.c +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.c 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_video.c 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_video.c + * +- * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,82 +14,93 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#include "hdhomerun.h" ++#include "hdhomerun_os.h" ++#include "hdhomerun_pkt.h" ++#include "hdhomerun_video.h" + + struct hdhomerun_video_sock_t { +- pthread_mutex_t lock; + uint8_t *buffer; + size_t buffer_size; + volatile size_t head; + volatile size_t tail; + size_t advance; ++ volatile bool_t running; + volatile bool_t terminate; + pthread_t thread; + int sock; +- uint32_t rtp_sequence; +- struct hdhomerun_debug_t *dbg; +- volatile uint32_t packet_count; +- volatile uint32_t transport_error_count; +- volatile uint32_t network_error_count; +- volatile uint32_t sequence_error_count; +- volatile uint32_t overflow_error_count; +- volatile uint8_t sequence[0x2000]; + }; + +-static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg); ++static void *hdhomerun_video_thread(void *arg); + +-struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size, struct hdhomerun_debug_t *dbg) ++static bool_t hdhomerun_video_bind_sock_internal(struct hdhomerun_video_sock_t *vs, uint16_t listen_port) ++{ ++ struct sockaddr_in sock_addr; ++ memset(&sock_addr, 0, sizeof(sock_addr)); ++ sock_addr.sin_family = AF_INET; ++ sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); ++ sock_addr.sin_port = htons(listen_port); ++ if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static bool_t hdhomerun_video_bind_sock(struct hdhomerun_video_sock_t *vs, uint16_t listen_port) ++{ ++ if (listen_port != 0) { ++ return hdhomerun_video_bind_sock_internal(vs, listen_port); ++ } ++ ++#if defined(__CYGWIN__) || defined(__WINDOWS__) ++ /* Windows firewall silently blocks a listening port if the port number is not explicitly given. */ ++ /* Workaround - pick a random port number. The port may already be in use to try multiple port numbers. */ ++ srand((int)getcurrenttime()); ++ int retry; ++ for (retry = 8; retry > 0; retry--) { ++ uint16_t listen_port = (uint16_t)((rand() % 32768) + 32768); ++ if (hdhomerun_video_bind_sock_internal(vs, listen_port)) { ++ return TRUE; ++ } ++ } ++ return FALSE; ++#else ++ return hdhomerun_video_bind_sock_internal(vs, listen_port); ++#endif ++} ++ ++struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size) + { + /* Create object. */ + struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)calloc(1, sizeof(struct hdhomerun_video_sock_t)); + if (!vs) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate video object\n"); + return NULL; + } + +- vs->dbg = dbg; +- vs->sock = -1; +- pthread_mutex_init(&vs->lock, NULL); +- +- /* Reset sequence tracking. */ +- hdhomerun_video_flush(vs); +- + /* Buffer size. */ + vs->buffer_size = (buffer_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; + if (vs->buffer_size == 0) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: invalid buffer size (%lu bytes)\n", (unsigned long)buffer_size); +- goto error; ++ free(vs); ++ return NULL; + } + vs->buffer_size += VIDEO_DATA_PACKET_SIZE; + + /* Create buffer. */ + vs->buffer = (uint8_t *)malloc(vs->buffer_size); + if (!vs->buffer) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate buffer (%lu bytes)\n", (unsigned long)vs->buffer_size); +- goto error; ++ free(vs); ++ return NULL; + } + + /* Create socket. */ + vs->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); + if (vs->sock == -1) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n"); +- goto error; ++ free(vs->buffer); ++ free(vs); ++ return NULL; + } + + /* Expand socket buffer size. */ +@@ -101,44 +112,30 @@ + setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); + + /* Bind socket. */ +- struct sockaddr_in sock_addr; +- memset(&sock_addr, 0, sizeof(sock_addr)); +- sock_addr.sin_family = AF_INET; +- sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); +- sock_addr.sin_port = htons(listen_port); +- if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to bind socket (port %u)\n", listen_port); +- goto error; ++ if (!hdhomerun_video_bind_sock(vs, listen_port)) { ++ hdhomerun_video_destroy(vs); ++ return NULL; + } + + /* Start thread. */ +- if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread_execute, vs) != 0) { +- hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to start thread\n"); +- goto error; ++ if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread, vs) != 0) { ++ hdhomerun_video_destroy(vs); ++ return NULL; + } ++ vs->running = 1; + + /* Success. */ + return vs; +- +-error: +- if (vs->sock != -1) { +- close(vs->sock); +- } +- if (vs->buffer) { +- free(vs->buffer); +- } +- free(vs); +- return NULL; + } + + void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs) + { +- vs->terminate = TRUE; +- pthread_join(vs->thread, NULL); +- ++ if (vs->running) { ++ vs->terminate = 1; ++ pthread_join(vs->thread, NULL); ++ } + close(vs->sock); + free(vs->buffer); +- + free(vs); + } + +@@ -147,85 +144,25 @@ + struct sockaddr_in sock_addr; + socklen_t sockaddr_size = sizeof(sock_addr); + if (getsockname(vs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) { +- hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_get_local_port: getsockname failed (%d)\n", sock_getlasterror); + return 0; + } +- + return ntohs(sock_addr.sin_port); + } + +-static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr) +-{ +- uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2]; +- if (packet_identifier == 0x1FFF) { +- return; +- } +- +- bool_t transport_error = ptr[1] >> 7; +- if (transport_error) { +- vs->transport_error_count++; +- vs->sequence[packet_identifier] = 0xFF; +- return; +- } +- +- uint8_t continuity_counter = ptr[3] & 0x0F; +- uint8_t previous_sequence = vs->sequence[packet_identifier]; +- +- if (continuity_counter == ((previous_sequence + 1) & 0x0F)) { +- vs->sequence[packet_identifier] = continuity_counter; +- return; +- } +- if (previous_sequence == 0xFF) { +- vs->sequence[packet_identifier] = continuity_counter; +- return; +- } +- if (continuity_counter == previous_sequence) { +- return; +- } +- +- vs->sequence_error_count++; +- vs->sequence[packet_identifier] = continuity_counter; +-} +- +-static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt) ++int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs) + { +- pkt->pos += 2; +- uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt); +- pkt->pos += 8; +- +- if (rtp_sequence != ((vs->rtp_sequence + 1) & 0xFFFF)) { +- if (vs->rtp_sequence != 0xFFFFFFFF) { +- vs->network_error_count++; +- +- /* restart pid sequence check */ +- /* can't use memset bcs sequence is volatile */ +- int i; +- for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++) +- vs->sequence[i] = 0xFF; +- } +- } +- +- vs->rtp_sequence = rtp_sequence; ++ return vs->sock; + } + +-static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg) ++static void *hdhomerun_video_thread(void *arg) + { + struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)arg; +- struct hdhomerun_pkt_t pkt_inst; + + while (!vs->terminate) { +- struct hdhomerun_pkt_t *pkt = &pkt_inst; +- hdhomerun_pkt_reset(pkt); ++ size_t head = vs->head; + + /* Receive. */ +- int length = recv(vs->sock, (char *)pkt->end, VIDEO_RTP_DATA_PACKET_SIZE, 0); +- pkt->end += length; +- +- if (length == VIDEO_RTP_DATA_PACKET_SIZE) { +- hdhomerun_video_parse_rtp(vs, pkt); +- length = (int)(pkt->end - pkt->pos); +- } +- ++ int length = recv(vs->sock, (char *)vs->buffer + head, VIDEO_DATA_PACKET_SIZE, 0); + if (length != VIDEO_DATA_PACKET_SIZE) { + if (length > 0) { + /* Data received but not valid - ignore. */ +@@ -235,27 +172,10 @@ + /* Wait for more data. */ + continue; + } +- vs->terminate = TRUE; ++ vs->terminate = 1; + return NULL; + } + +- pthread_mutex_lock(&vs->lock); +- +- /* Store in ring buffer. */ +- size_t head = vs->head; +- uint8_t *ptr = vs->buffer + head; +- memcpy(ptr, pkt->pos, length); +- +- /* Stats. */ +- vs->packet_count++; +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 0); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 1); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 2); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 3); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 4); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 5); +- hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 6); +- + /* Calculate new head. */ + head += length; + if (head >= vs->buffer_size) { +@@ -264,15 +184,11 @@ + + /* Check for buffer overflow. */ + if (head == vs->tail) { +- vs->overflow_error_count++; +- pthread_mutex_unlock(&vs->lock); + continue; + } + + /* Atomic update. */ + vs->head = head; +- +- pthread_mutex_unlock(&vs->lock); + } + + return NULL; +@@ -280,8 +196,6 @@ + + uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size) + { +- pthread_mutex_lock(&vs->lock); +- + size_t head = vs->head; + size_t tail = vs->tail; + +@@ -298,7 +212,6 @@ + if (head == tail) { + vs->advance = 0; + *pactual_size = 0; +- pthread_mutex_unlock(&vs->lock); + return NULL; + } + +@@ -306,7 +219,6 @@ + if (size == 0) { + vs->advance = 0; + *pactual_size = 0; +- pthread_mutex_unlock(&vs->lock); + return NULL; + } + +@@ -321,58 +233,13 @@ + } + vs->advance = size; + *pactual_size = size; +- uint8_t *result = vs->buffer + tail; +- +- pthread_mutex_unlock(&vs->lock); +- return result; ++ return vs->buffer + tail; + } + + void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs) + { +- pthread_mutex_lock(&vs->lock); +- ++ /* Atomic update of tail. */ + vs->tail = vs->head; + vs->advance = 0; +- +- /* can't use memset bcs sequence is volatile */ +- int i; +- for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++) +- vs->sequence[i] = 0xFF; +- +- vs->rtp_sequence = 0xFFFFFFFF; +- +- vs->packet_count = 0; +- vs->transport_error_count = 0; +- vs->network_error_count = 0; +- vs->sequence_error_count = 0; +- vs->overflow_error_count = 0; +- +- pthread_mutex_unlock(&vs->lock); + } + +-void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs) +-{ +- struct hdhomerun_video_stats_t stats; +- hdhomerun_video_get_stats(vs, &stats); +- +- hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n", +- stats.packet_count, stats.network_error_count, +- stats.transport_error_count, stats.sequence_error_count, +- stats.overflow_error_count +- ); +-} +- +-void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats) +-{ +- memset(stats, 0, sizeof(struct hdhomerun_video_stats_t)); +- +- pthread_mutex_lock(&vs->lock); +- +- stats->packet_count = vs->packet_count; +- stats->network_error_count = vs->network_error_count; +- stats->transport_error_count = vs->transport_error_count; +- stats->sequence_error_count = vs->sequence_error_count; +- stats->overflow_error_count = vs->overflow_error_count; +- +- pthread_mutex_unlock(&vs->lock); +-} +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.h src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_video.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/hdhomerun_video.h 2009-01-09 13:14:56.000000000 +1030 +@@ -1,12 +1,12 @@ + /* + * hdhomerun_video.h + * +- * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>. ++ * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. + * +- * This library is free software; you can redistribute it and/or ++ * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either +- * version 3 of the License, or (at your option) any later version. ++ * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +@@ -14,20 +14,8 @@ + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- * As a special exception to the GNU Lesser General Public License, +- * you may link, statically or dynamically, an application with a +- * publicly distributed version of the Library to produce an +- * executable file containing portions of the Library, and +- * distribute that executable file under terms of your choice, +- * without any of the additional requirements listed in clause 4 of +- * the GNU Lesser General Public License. +- * +- * By "a publicly distributed version of the Library", we mean +- * either the unmodified Library as distributed by Silicondust, or a +- * modified version of the Library that is distributed under the +- * conditions defined in the GNU Lesser General Public License. ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifdef __cplusplus + extern "C" { +@@ -35,40 +23,34 @@ + + struct hdhomerun_video_sock_t; + +-struct hdhomerun_video_stats_t { +- uint32_t packet_count; +- uint32_t network_error_count; +- uint32_t transport_error_count; +- uint32_t sequence_error_count; +- uint32_t overflow_error_count; +-}; +- + #define TS_PACKET_SIZE 188 + #define VIDEO_DATA_PACKET_SIZE (188 * 7) + #define VIDEO_DATA_BUFFER_SIZE_1S (20000000 / 8) + +-#define VIDEO_RTP_DATA_PACKET_SIZE ((188 * 7) + 12) +- + /* + * Create a video/data socket. + * + * uint16_t listen_port: Port number to listen on. Set to 0 to auto-select. + * size_t buffer_size: Size of receive buffer. For 1 second of buffer use VIDEO_DATA_BUFFER_SIZE_1S. +- * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. + * + * Returns a pointer to the newly created control socket. + * + * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. + */ +-extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size, struct hdhomerun_debug_t *dbg); +-extern LIBTYPE void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs); ++extern struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size); ++extern void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs); + + /* + * Get the port the socket is listening on. + * + * Returns 16-bit port with native endianness, or 0 on error. + */ +-extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); ++extern uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); ++ ++/* ++ * Get the low-level socket handle. ++ */ ++extern int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs); + + /* + * Read data from buffer. +@@ -87,18 +69,12 @@ + * The buffer is implemented as a ring buffer. It is possible for this function to return a small + * amount of data when more is available due to the wrap-around case. + */ +-extern LIBTYPE uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size); ++extern uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size); + + /* + * Flush the buffer. + */ +-extern LIBTYPE void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs); +- +-/* +- * Debug print internal stats. +- */ +-extern LIBTYPE void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs); +-extern LIBTYPE void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats); ++extern void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs); + + #ifdef __cplusplus + } +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/lgpl.txt src/mythtv-0.21/libs/libmythtv/hdhomerun/lgpl.txt +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhomerun/lgpl.txt 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhomerun/lgpl.txt 2009-01-09 13:14:56.000000000 +1030 +@@ -1,165 +1,504 @@ +- GNU LESSER GENERAL PUBLIC LICENSE +- Version 3, 29 June 2007 ++ GNU LESSER GENERAL PUBLIC LICENSE ++ Version 2.1, February 1999 + +- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> ++ Copyright (C) 1991, 1999 Free Software Foundation, Inc. ++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +- +- This version of the GNU Lesser General Public License incorporates +-the terms and conditions of version 3 of the GNU General Public +-License, supplemented by the additional permissions listed below. +- +- 0. Additional Definitions. +- +- As used herein, "this License" refers to version 3 of the GNU Lesser +-General Public License, and the "GNU GPL" refers to version 3 of the GNU +-General Public License. +- +- "The Library" refers to a covered work governed by this License, +-other than an Application or a Combined Work as defined below. +- +- An "Application" is any work that makes use of an interface provided +-by the Library, but which is not otherwise based on the Library. +-Defining a subclass of a class defined by the Library is deemed a mode +-of using an interface provided by the Library. +- +- A "Combined Work" is a work produced by combining or linking an +-Application with the Library. The particular version of the Library +-with which the Combined Work was made is also called the "Linked +-Version". +- +- The "Minimal Corresponding Source" for a Combined Work means the +-Corresponding Source for the Combined Work, excluding any source code +-for portions of the Combined Work that, considered in isolation, are +-based on the Application, and not on the Linked Version. +- +- The "Corresponding Application Code" for a Combined Work means the +-object code and/or source code for the Application, including any data +-and utility programs needed for reproducing the Combined Work from the +-Application, but excluding the System Libraries of the Combined Work. +- +- 1. Exception to Section 3 of the GNU GPL. +- +- You may convey a covered work under sections 3 and 4 of this License +-without being bound by section 3 of the GNU GPL. +- +- 2. Conveying Modified Versions. +- +- If you modify a copy of the Library, and, in your modifications, a +-facility refers to a function or data to be supplied by an Application +-that uses the facility (other than as an argument passed when the +-facility is invoked), then you may convey a copy of the modified +-version: +- +- a) under this License, provided that you make a good faith effort to +- ensure that, in the event an Application does not supply the +- function or data, the facility still operates, and performs +- whatever part of its purpose remains meaningful, or +- +- b) under the GNU GPL, with none of the additional permissions of +- this License applicable to that copy. +- +- 3. Object Code Incorporating Material from Library Header Files. +- +- The object code form of an Application may incorporate material from +-a header file that is part of the Library. You may convey such object +-code under terms of your choice, provided that, if the incorporated +-material is not limited to numerical parameters, data structure +-layouts and accessors, or small macros, inline functions and templates +-(ten or fewer lines in length), you do both of the following: +- +- a) Give prominent notice with each copy of the object code that the +- Library is used in it and that the Library and its use are +- covered by this License. +- +- b) Accompany the object code with a copy of the GNU GPL and this license +- document. +- +- 4. Combined Works. +- +- You may convey a Combined Work under terms of your choice that, +-taken together, effectively do not restrict modification of the +-portions of the Library contained in the Combined Work and reverse +-engineering for debugging such modifications, if you also do each of +-the following: +- +- a) Give prominent notice with each copy of the Combined Work that +- the Library is used in it and that the Library and its use are +- covered by this License. +- +- b) Accompany the Combined Work with a copy of the GNU GPL and this license +- document. +- +- c) For a Combined Work that displays copyright notices during +- execution, include the copyright notice for the Library among +- these notices, as well as a reference directing the user to the +- copies of the GNU GPL and this license document. +- +- d) Do one of the following: +- +- 0) Convey the Minimal Corresponding Source under the terms of this +- License, and the Corresponding Application Code in a form +- suitable for, and under terms that permit, the user to +- recombine or relink the Application with a modified version of +- the Linked Version to produce a modified Combined Work, in the +- manner specified by section 6 of the GNU GPL for conveying +- Corresponding Source. +- +- 1) Use a suitable shared library mechanism for linking with the +- Library. A suitable mechanism is one that (a) uses at run time +- a copy of the Library already present on the user's computer +- system, and (b) will operate properly with a modified version +- of the Library that is interface-compatible with the Linked +- Version. +- +- e) Provide Installation Information, but only if you would otherwise +- be required to provide such information under section 6 of the +- GNU GPL, and only to the extent that such information is +- necessary to install and execute a modified version of the +- Combined Work produced by recombining or relinking the +- Application with a modified version of the Linked Version. (If +- you use option 4d0, the Installation Information must accompany +- the Minimal Corresponding Source and Corresponding Application +- Code. If you use option 4d1, you must provide the Installation +- Information in the manner specified by section 6 of the GNU GPL +- for conveying Corresponding Source.) +- +- 5. Combined Libraries. +- +- You may place library facilities that are a work based on the +-Library side by side in a single library together with other library +-facilities that are not Applications and are not covered by this +-License, and convey such a combined library under terms of your +-choice, if you do both of the following: +- +- a) Accompany the combined library with a copy of the same work based +- on the Library, uncombined with any other library facilities, +- conveyed under the terms of this License. +- +- b) Give prominent notice with the combined library that part of it +- is a work based on the Library, and explaining where to find the +- accompanying uncombined form of the same work. +- +- 6. Revised Versions of the GNU Lesser General Public License. +- +- The Free Software Foundation may publish revised and/or new versions +-of the GNU Lesser General Public License from time to time. Such new +-versions will be similar in spirit to the present version, but may +-differ in detail to address new problems or concerns. +- +- Each version is given a distinguishing version number. If the +-Library as you received it specifies that a certain numbered version +-of the GNU Lesser General Public License "or any later version" +-applies to it, you have the option of following the terms and +-conditions either of that published version or of any later version +-published by the Free Software Foundation. If the Library as you +-received it does not specify a version number of the GNU Lesser +-General Public License, you may choose any version of the GNU Lesser +-General Public License ever published by the Free Software Foundation. +- +- If the Library as you received it specifies that a proxy can decide +-whether future versions of the GNU Lesser General Public License shall +-apply, that proxy's public statement of acceptance of any version is +-permanent authorization for you to choose that version for the ++[This is the first released version of the Lesser GPL. It also counts ++ as the successor of the GNU Library Public License, version 2, hence ++ the version number 2.1.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++Licenses are intended to guarantee your freedom to share and change ++free software--to make sure the software is free for all its users. ++ ++ This license, the Lesser General Public License, applies to some ++specially designated software packages--typically libraries--of the ++Free Software Foundation and other authors who decide to use it. You ++can use it too, but we suggest you first think carefully about whether ++this license or the ordinary General Public License is the better ++strategy to use in any particular case, based on the explanations below. ++ ++ When we speak of free software, we are referring to freedom of use, ++not price. Our General Public Licenses are designed to make sure that ++you have the freedom to distribute copies of free software (and charge ++for this service if you wish); that you receive source code or can get ++it if you want it; that you can change the software and use pieces of ++it in new free programs; and that you are informed that you can do ++these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++distributors to deny you these rights or to ask you to surrender these ++rights. These restrictions translate to certain responsibilities for ++you if you distribute copies of the library or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++or for a fee, you must give the recipients all the rights that we gave ++you. You must make sure that they, too, receive or can get the source ++code. If you link other code with the library, you must provide ++complete object files to the recipients, so that they can relink them ++with the library after making changes to the library and recompiling ++it. And you must show them these terms so they know their rights. ++ ++ We protect your rights with a two-step method: (1) we copyright the ++library, and (2) we offer you this license, which gives you legal ++permission to copy, distribute and/or modify the library. ++ ++ To protect each distributor, we want to make it very clear that ++there is no warranty for the free library. Also, if the library is ++modified by someone else and passed on, the recipients should know ++that what they have is not the original version, so that the original ++author's reputation will not be affected by problems that might be ++introduced by others. ++ ++ Finally, software patents pose a constant threat to the existence of ++any free program. We wish to make sure that a company cannot ++effectively restrict the users of a free program by obtaining a ++restrictive license from a patent holder. Therefore, we insist that ++any patent license obtained for a version of the library must be ++consistent with the full freedom of use specified in this license. ++ ++ Most GNU software, including some libraries, is covered by the ++ordinary GNU General Public License. This license, the GNU Lesser ++General Public License, applies to certain designated libraries, and ++is quite different from the ordinary General Public License. We use ++this license for certain libraries in order to permit linking those ++libraries into non-free programs. ++ ++ When a program is linked with a library, whether statically or using ++a shared library, the combination of the two is legally speaking a ++combined work, a derivative of the original library. The ordinary ++General Public License therefore permits such linking only if the ++entire combination fits its criteria of freedom. The Lesser General ++Public License permits more lax criteria for linking other code with ++the library. ++ ++ We call this license the "Lesser" General Public License because it ++does Less to protect the user's freedom than the ordinary General ++Public License. It also provides other free software developers Less ++of an advantage over competing non-free programs. These disadvantages ++are the reason we use the ordinary General Public License for many ++libraries. However, the Lesser license provides advantages in certain ++special circumstances. ++ ++ For example, on rare occasions, there may be a special need to ++encourage the widest possible use of a certain library, so that it becomes ++a de-facto standard. To achieve this, non-free programs must be ++allowed to use the library. A more frequent case is that a free ++library does the same job as widely used non-free libraries. In this ++case, there is little to gain by limiting the free library to free ++software only, so we use the Lesser General Public License. ++ ++ In other cases, permission to use a particular library in non-free ++programs enables a greater number of people to use a large body of ++free software. For example, permission to use the GNU C Library in ++non-free programs enables many more people to use the whole GNU ++operating system, as well as its variant, the GNU/Linux operating ++system. ++ ++ Although the Lesser General Public License is Less protective of the ++users' freedom, it does ensure that the user of a program that is ++linked with the Library has the freedom and the wherewithal to run ++that program using a modified version of the Library. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. Pay close attention to the difference between a ++"work based on the library" and a "work that uses the library". The ++former contains code derived from the library, whereas the latter must ++be combined with the library in order to run. ++ ++ GNU LESSER GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library or other ++program which contains a notice placed by the copyright holder or ++other authorized party saying it may be distributed under the terms of ++this Lesser General Public License (also called "this License"). ++Each licensee is addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++prepared so as to be conveniently linked with application programs ++(which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++which has been distributed under these terms. A "work based on the ++Library" means either the Library or any derivative work under ++copyright law: that is to say, a work containing the Library or a ++portion of it, either verbatim or with modifications and/or translated ++straightforwardly into another language. (Hereinafter, translation is ++included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++making modifications to it. For a library, complete source code means ++all the source code for all modules it contains, plus any associated ++interface definition files, plus the scripts used to control compilation ++and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running a program using the Library is not restricted, and output from ++such a program is covered only if its contents constitute a work based ++on the Library (independent of the use of the Library in a tool for ++writing it). Whether that is true depends on what the Library does ++and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++complete source code as you receive it, in any medium, provided that ++you conspicuously and appropriately publish on each copy an ++appropriate copyright notice and disclaimer of warranty; keep intact ++all the notices that refer to this License and to the absence of any ++warranty; and distribute a copy of this License along with the + Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++and you may at your option offer warranty protection in exchange for a ++fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++of it, thus forming a work based on the Library, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Library, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Library, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote ++it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Library. ++ ++In addition, mere aggregation of another work not based on the Library ++with the Library (or with a work based on the Library) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++License instead of this License to a given copy of the Library. To do ++this, you must alter all the notices that refer to this License, so ++that they refer to the ordinary GNU General Public License, version 2, ++instead of to this License. (If a newer version than version 2 of the ++ordinary GNU General Public License has appeared, then you can specify ++that version instead if you wish.) Do not make any other change in ++these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++that copy, so the ordinary GNU General Public License applies to all ++subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++derivative of it, under Section 2) in object code or executable form ++under the terms of Sections 1 and 2 above provided that you accompany ++it with the complete corresponding machine-readable source code, which ++must be distributed under the terms of Sections 1 and 2 above on a ++medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++from a designated place, then offering equivalent access to copy the ++source code from the same place satisfies the requirement to ++distribute the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++Library, but is designed to work with the Library by being compiled or ++linked with it, is called a "work that uses the Library". Such a ++work, in isolation, is not a derivative work of the Library, and ++therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++creates an executable that is a derivative of the Library (because it ++contains portions of the Library), rather than a "work that uses the ++library". The executable is therefore covered by this License. ++Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++that is part of the Library, the object code for the work may be a ++derivative work of the Library even though the source code is not. ++Whether this is true is especially significant if the work can be ++linked without the Library, or if the work is itself a library. The ++threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++structure layouts and accessors, and small macros and small inline ++functions (ten lines or less in length), then the use of the object ++file is unrestricted, regardless of whether it is legally a derivative ++work. (Executables containing this object code plus portions of the ++Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++distribute the object code for the work under the terms of Section 6. ++Any executables containing that work also fall under Section 6, ++whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also combine or ++link a "work that uses the Library" with the Library to produce a ++work containing portions of the Library, and distribute that work ++under terms of your choice, provided that the terms permit ++modification of the work for the customer's own use and reverse ++engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++Library is used in it and that the Library and its use are covered by ++this License. You must supply a copy of this License. If the work ++during execution displays copyright notices, you must include the ++copyright notice for the Library among them, as well as a reference ++directing the user to the copy of this License. Also, you must do one ++of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Use a suitable shared library mechanism for linking with the ++ Library. A suitable mechanism is one that (1) uses at run time a ++ copy of the library already present on the user's computer system, ++ rather than copying library functions into the executable, and (2) ++ will operate properly with a modified version of the library, if ++ the user installs one, as long as the modified version is ++ interface-compatible with the version that the work was made with. ++ ++ c) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ d) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ e) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++Library" must include any data and utility programs needed for ++reproducing the executable from it. However, as a special exception, ++the materials to be distributed need not include anything that is ++normally distributed (in either source or binary form) with the major ++components (compiler, kernel, and so on) of the operating system on ++which the executable runs, unless that component itself accompanies ++the executable. ++ ++ It may happen that this requirement contradicts the license ++restrictions of other proprietary libraries that do not normally ++accompany the operating system. Such a contradiction means you cannot ++use both them and the Library together in an executable that you ++distribute. ++ ++ 7. You may place library facilities that are a work based on the ++Library side-by-side in a single library together with other library ++facilities not covered by this License, and distribute such a combined ++library, provided that the separate distribution of the work based on ++the Library and of the other library facilities is otherwise ++permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++the Library except as expressly provided under this License. Any ++attempt otherwise to copy, modify, sublicense, link with, or ++distribute the Library is void, and will automatically terminate your ++rights under this License. However, parties who have received copies, ++or rights, from you under this License will not have their licenses ++terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Library or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Library (or any work based on the ++Library), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++Library), the recipient automatically receives a license from the ++original licensor to copy, distribute, link with or modify the Library ++subject to these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties with ++this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Library at all. For example, if a patent ++license would not permit royalty-free redistribution of the Library by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Library. ++ ++If any portion of this section is held invalid or unenforceable under any ++particular circumstance, the balance of the section is intended to apply, ++and the section as a whole is intended to apply in other circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Library under this License may add ++an explicit geographical distribution limitation excluding those countries, ++so that distribution is permitted only in or among countries not thus ++excluded. In such case, this License incorporates the limitation as if ++written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++versions of the Lesser General Public License from time to time. ++Such new versions will be similar in spirit to the present version, ++but may differ in detail to address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Library ++specifies a version number of this License which applies to it and ++"any later version", you have the option of following the terms and ++conditions either of that version or of any later version published by ++the Free Software Foundation. If the Library does not specify a ++license version number, you may choose any version ever published by ++the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++programs whose distribution conditions are incompatible with these, ++write to the author to ask for permission. For software which is ++copyrighted by the Free Software Foundation, write to the Free ++Software Foundation; we sometimes make exceptions for this. Our ++decision will be guided by the two goals of preserving the free status ++of all derivatives of our free software and of promoting the sharing ++and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++possible use to the public, we recommend making it free software that ++everyone can redistribute and change. You can do so by permitting ++redistribution under these terms (or, alternatively, under the terms of the ++ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++safest to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least the ++"copyright" line and a pointer to where the full notice is found. ++ ++ <one line to give the library's name and a brief idea of what it does.> ++ Copyright (C) <year> <name of author> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the library, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ <signature of Ty Coon>, 1 April 1990 ++ Ty Coon, President of Vice ++ ++That's all there is to it! ++ ++ +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrchannel.cpp src/mythtv-0.21/libs/libmythtv/hdhrchannel.cpp +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrchannel.cpp 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhrchannel.cpp 2009-01-09 13:14:58.000000000 +1030 +@@ -1,6 +1,6 @@ + /** +- * HDHRChannel +- * Copyright (c) 2006-2009 by Silicondust Engineering Ltd. ++ * DBox2Channel ++ * Copyright (c) 2006 by Silicondust Engineering Ltd. + * Distributed as part of MythTV under GPL v2 and later. + */ + +@@ -24,6 +24,7 @@ + #include "hdhrchannel.h" + #include "videosource.h" + #include "channelutil.h" ++#include "frequencytables.h" + + #define DEBUG_PID_FILTERS + +@@ -31,7 +32,7 @@ + #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) + + HDHRChannel::HDHRChannel(TVRec *parent, const QString &device, uint tuner) +- : DTVChannel(parent), _hdhomerun_device(NULL), ++ : DTVChannel(parent), _control_socket(NULL), + _device_id(0), _device_ip(0), + _tuner(tuner), _lock(true) + { +@@ -41,8 +42,6 @@ + if (valid && hdhomerun_discover_validate_device_id(_device_id)) + return; + +- _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; +- + /* Otherwise, is it a valid IP address? */ + struct in_addr address; + if (inet_aton(device, &address)) +@@ -55,6 +54,7 @@ + VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Invalid DeviceID '%1'") + .arg(device)); + ++ _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; + } + + HDHRChannel::~HDHRChannel(void) +@@ -67,38 +67,77 @@ + if (IsOpen()) + return true; + ++ if (!FindDevice()) ++ return false; ++ + if (!InitializeInputs()) + return false; + +- return Connect(); ++ return (_device_ip != 0) && Connect(); + } + + void HDHRChannel::Close(void) + { +- if (_hdhomerun_device) ++ if (_control_socket) + { +- hdhomerun_device_destroy(_hdhomerun_device); +- _hdhomerun_device = NULL; ++ hdhomerun_control_destroy(_control_socket); ++ _control_socket = NULL; + } + } + + bool HDHRChannel::EnterPowerSavingMode(void) + { +- return hdhomerun_device_set_tuner_channel(_hdhomerun_device, "none") > 0; ++ return QString::null != TunerSet("channel", "none", false); ++} ++ ++bool HDHRChannel::FindDevice(void) ++{ ++ if (!_device_id) ++ return _device_ip; ++ ++ _device_ip = 0; ++ ++ /* Discover. */ ++ struct hdhomerun_discover_device_t result; ++ int ret = hdhomerun_discover_find_device(_device_id, &result); ++ if (ret < 0) ++ { ++ VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO); ++ return false; ++ } ++ if (ret == 0) ++ { ++ VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found")); ++ return false; ++ } ++ ++ /* Found. */ ++ _device_ip = result.ip_addr; ++ ++ VERBOSE(VB_IMPORTANT, LOC + ++ QString("device found at address %1.%2.%3.%4") ++ .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) ++ .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF)); ++ ++ return true; + } + + bool HDHRChannel::Connect(void) + { +- _hdhomerun_device = hdhomerun_device_create( +- _device_id, _device_ip, _tuner, NULL); ++ _control_socket = hdhomerun_control_create(_device_id, _device_ip); ++ if (!_control_socket) ++ { ++ VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); ++ return false; ++ } + +- if (!_hdhomerun_device) ++ if (hdhomerun_control_get_local_addr(_control_socket) == 0) + { +- VERBOSE(VB_IMPORTANT, +- LOC_ERR + "Unable to create hdhomerun device object"); ++ VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); + return false; + } + ++ VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device"); + return true; + } + +@@ -106,7 +145,7 @@ + { + QMutexLocker locker(&_lock); + +- if (!_hdhomerun_device) ++ if (!_control_socket) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); + return QString::null; +@@ -114,7 +153,7 @@ + + char *value = NULL; + char *error = NULL; +- if (hdhomerun_device_get_var(_hdhomerun_device, name, &value, &error) < 0) ++ if (hdhomerun_control_get(_control_socket, name, &value, &error) < 0) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); + return QString::null; +@@ -136,7 +175,7 @@ + { + QMutexLocker locker(&_lock); + +- if (!_hdhomerun_device) ++ if (!_control_socket) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); + return QString::null; +@@ -144,8 +183,7 @@ + + char *value = NULL; + char *error = NULL; +- if (hdhomerun_device_set_var( +- _hdhomerun_device, name, val, &value, &error) < 0) ++ if (hdhomerun_control_set(_control_socket, name, val, &value, &error) < 0) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); + +@@ -163,11 +201,6 @@ + return QString(value); + } + +-struct hdhomerun_device_t *HDHRChannel::GetHDHRDevice(void) +-{ +- return _hdhomerun_device; +-} +- + QString HDHRChannel::TunerGet(const QString &name, bool report_error_return) + { + return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name), +@@ -188,8 +221,7 @@ + return false; + } + +- unsigned long localIP = hdhomerun_device_get_local_machine_addr( +- _hdhomerun_device); ++ unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); + if (localIP == 0) + { + return false; +@@ -200,7 +232,7 @@ + .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) + .arg(localPort); + +- if (hdhomerun_device_set_tuner_target(_hdhomerun_device, configValue) <= 0) ++ if (!TunerSet("target", configValue)) + { + return false; + } +@@ -208,9 +240,9 @@ + return true; + } + +-bool HDHRChannel::DeviceClearTarget(void) ++bool HDHRChannel::DeviceClearTarget() + { +- return hdhomerun_device_set_tuner_target(_hdhomerun_device, "none") > 0; ++ return TunerSet("target", "0.0.0.0:0"); + } + + bool HDHRChannel::SetChannelByString(const QString &channum) +@@ -316,8 +348,7 @@ + if (mpeg_prog_num && (GetTuningMode() == "mpeg")) + { + QString pnum = QString::number(mpeg_prog_num); +- _ignore_filters = (hdhomerun_device_set_tuner_program( +- _hdhomerun_device, pnum) > 0); ++ _ignore_filters = QString::null != TunerSet("program", pnum, false); + } + + return true; +@@ -360,27 +391,22 @@ + bool HDHRChannel::Tune(uint frequency, QString /*input*/, + QString modulation, QString si_std) + { +- // Convert dtv_multiplex.modulation strings to something the HDHR can use: +- modulation.replace("qam_", "qam"); // e.g. qam_256 -> qam256 +-#if 0 +- if (modulation == "qamauto") +- modulation = "qam"; // "auto" works just as well? +-#endif +- +- if (modulation.isEmpty()) +- modulation = "auto"; ++ bool ok = false; + +- QString chan = modulation + ':' + QString::number(frequency); ++ VERBOSE(VB_CHANNEL, LOC + ++ QString("TuneTo(%1,%2)").arg(frequency).arg(modulation)); + +- VERBOSE(VB_CHANNEL, LOC + "Tune()ing to " + chan); ++ if (modulation == "8vsb") ++ ok = TunerSet("channel", QString("8vsb:%1").arg(frequency)); ++ else if (modulation == "qam_64") ++ ok = TunerSet("channel", QString("qam64:%1").arg(frequency)); ++ else if (modulation == "qam_256") ++ ok = TunerSet("channel", QString("qam256:%1").arg(frequency)); + +- if (hdhomerun_device_set_tuner_channel(_hdhomerun_device, chan) > 0) +- { ++ if (ok) + SetSIStandard(si_std); +- return true; +- } + +- return false; ++ return ok; + } + + bool HDHRChannel::AddPID(uint pid, bool do_update) +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrchannel.h src/mythtv-0.21/libs/libmythtv/hdhrchannel.h +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrchannel.h 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhrchannel.h 2009-01-09 13:14:58.000000000 +1030 +@@ -39,7 +39,7 @@ + bool SetChannelByString(const QString &chan); + + // Gets +- bool IsOpen(void) const { return (_hdhomerun_device != NULL); } ++ bool IsOpen(void) const { return (_control_socket != NULL); } + QString GetDevice(void) const + { return QString("%1/%2").arg(_device_id, 8, 16).arg(_tuner); } + vector<uint> GetPIDs(void) const +@@ -57,13 +57,11 @@ + bool Tune(const DTVMultiplex &tuning, QString inputname); + + private: ++ bool FindDevice(void); + bool Connect(void); + bool Tune(uint frequency, QString inputname, + QString modulation, QString si_std); + +- +- struct hdhomerun_device_t *GetHDHRDevice(void); +- + bool DeviceSetTarget(unsigned short localPort); + bool DeviceClearTarget(void); + +@@ -76,7 +74,7 @@ + bool report_error_return = true); + + private: +- struct hdhomerun_device_t *_hdhomerun_device; ++ hdhr_socket_t *_control_socket; + uint _device_id; + uint _device_ip; + uint _tuner; +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrrecorder.cpp src/mythtv-0.21/libs/libmythtv/hdhrrecorder.cpp +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrrecorder.cpp 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhrrecorder.cpp 2009-01-22 18:52:43.000000000 +1030 +@@ -1,6 +1,6 @@ + /** -*- Mode: c++ -*- + * HDHRRecorder +- * Copyright (c) 2006-2009 by Silicondust Engineering Ltd, and ++ * Copyright (c) 2006 by Silicondust Engineering Ltd, and + * Daniel Thor Kristjansson + * Distributed as part of MythTV under GPL v2 and later. + */ +@@ -27,7 +27,6 @@ + #include "hdhrrecorder.h" + #include "atsctables.h" + #include "atscstreamdata.h" +-#include "dvbstreamdata.h" + #include "eithelper.h" + #include "tv_rec.h" + +@@ -110,7 +109,7 @@ + buffersize = max(49 * TSPacket::SIZE * 128, buffersize); + + /* Create TS socket. */ +- _video_socket = hdhomerun_video_create(0, buffersize, NULL); ++ _video_socket = hdhomerun_video_create(0, buffersize); + if (!_video_socket) + { + VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); +@@ -177,13 +176,10 @@ + data->AddMPEGListener(this); + + ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(data); +- DVBStreamData *dvb = dynamic_cast<DVBStreamData*>(data); + + if (atsc && atsc->DesiredMinorChannel()) + atsc->SetDesiredChannel(atsc->DesiredMajorChannel(), + atsc->DesiredMinorChannel()); +- else if (dvb) +- dvb->AddDVBMainListener(this); + else if (data->DesiredProgram() >= 0) + data->SetDesiredProgram(data->DesiredProgram()); + } +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp src/mythtv-0.21/libs/libmythtv/hdhrsignalmonitor.cpp +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/hdhrsignalmonitor.cpp 2009-01-09 13:14:58.000000000 +1030 +@@ -139,17 +139,19 @@ + { + dtvMonitorRunning = true; + +- HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); +- struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice(); +- +- if (!_hdhomerun_device) ++ struct hdhomerun_video_sock_t *_video_socket; ++ _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); ++ if (!_video_socket) + { +- VERBOSE(VB_IMPORTANT, "Failed to get HDHomeRun device handle"); ++ VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket"); + return; + } + +- if (!hdhomerun_device_stream_start(_hdhomerun_device)) ++ HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); ++ uint localPort = hdhomerun_video_get_local_port(_video_socket); ++ if (!hdrc->DeviceSetTarget(localPort)) + { ++ hdhomerun_video_destroy(_video_socket); + VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target"); + return; + } +@@ -164,7 +166,7 @@ + + size_t data_length; + unsigned char *data_buffer = +- hdhomerun_device_stream_recv(_hdhomerun_device, ++ hdhomerun_video_recv(_video_socket, + VIDEO_DATA_BUFFER_SIZE_1S / 5, + &data_length); + +@@ -177,7 +179,8 @@ + usleep(2500); + } + +- hdhomerun_device_stream_stop(_hdhomerun_device); ++ hdrc->DeviceClearTarget(); ++ hdhomerun_video_destroy(_video_socket); + + VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown"); + +@@ -212,15 +215,16 @@ + return; + } + +- HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); +- struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice(); +- struct hdhomerun_tuner_status_t status; +- hdhomerun_device_get_tuner_status(_hdhomerun_device, NULL, &status); +- +- uint sig = status.signal_strength; +- uint snq = status.signal_to_noise_quality; +- uint seq = status.symbol_error_quality; +- ++ QString msg = ((HDHRChannel*)channel)->TunerGet("status"); ++ //ss = signal strength, [0,100] ++ //snq = signal to noise quality [0,100] ++ //seq = signal error quality [0,100] ++ int loc_sig = msg.find("ss="), loc_snq = msg.find("snq="); ++ int loc_seq = msg.find("seq="), loc_end = msg.length(); ++ bool ok0, ok1, ok2; ++ uint sig = msg.mid(loc_sig + 3, loc_snq - loc_sig - 4).toUInt(&ok0); ++ uint snq = msg.mid(loc_snq + 4, loc_seq - loc_snq - 5).toUInt(&ok1); ++ uint seq = msg.mid(loc_seq + 4, loc_end - loc_seq - 4).toUInt(&ok2); + (void) snq; // TODO should convert to S/N + (void) seq; // TODO should report this... + +@@ -232,8 +236,9 @@ + bool isLocked = false; + { + QMutexLocker locker(&statusLock); +- signalStrength.SetValue(sig); +- signalLock.SetValue(status.lock_supported); ++ if (loc_sig > 0 && loc_snq > 0 && ok0) ++ signalStrength.SetValue(sig); ++ signalLock.SetValue(signalStrength.IsGood() ? 1 : 0); + isLocked = signalLock.IsGood(); + } + +diff -aur branches/release-0-21-fixes/mythtv/libs/libmythtv/libmythtv.pro src/mythtv-0.21/libs/libmythtv/libmythtv.pro +--- branches/release-0-21-fixes/mythtv/libs/libmythtv/libmythtv.pro 2009-07-13 15:44:12.000000000 +0930 ++++ src/mythtv-0.21/libs/libmythtv/libmythtv.pro 2009-01-09 13:14:58.000000000 +1030 +@@ -459,28 +459,12 @@ + DEFINES += USING_HDHOMERUN + + # HDHomeRun library +- HEADERS += hdhomerun/hdhomerun.h ++ HEADERS += hdhomerun/hdhomerun_pkt.h hdhomerun/hdhomerun_discover.h ++ HEADERS += hdhomerun/hdhomerun_video.h hdhomerun/hdhomerun_control.h + HEADERS += hdhomerun/hdhomerun_os.h +- HEADERS += hdhomerun/hdhomerun_os_posix.h +- HEADERS += hdhomerun/hdhomerun_os_windows.h +- HEADERS += hdhomerun/hdhomerun_channelscan.h +- HEADERS += hdhomerun/hdhomerun_channels.h +- HEADERS += hdhomerun/hdhomerun_control.h +- HEADERS += hdhomerun/hdhomerun_debug.h +- HEADERS += hdhomerun/hdhomerun_pkt.h +- HEADERS += hdhomerun/hdhomerun_device.h +- HEADERS += hdhomerun/hdhomerun_types.h +- HEADERS += hdhomerun/hdhomerun_discover.h +- HEADERS += hdhomerun/hdhomerun_video.h +- +- SOURCES += hdhomerun/hdhomerun_pkt.c +- SOURCES += hdhomerun/hdhomerun_debug.c +- SOURCES += hdhomerun/hdhomerun_discover.c +- SOURCES += hdhomerun/hdhomerun_channels.c +- SOURCES += hdhomerun/hdhomerun_channelscan.c +- SOURCES += hdhomerun/hdhomerun_control.c +- SOURCES += hdhomerun/hdhomerun_video.c +- SOURCES += hdhomerun/hdhomerun_device.c ++ ++ SOURCES += hdhomerun/hdhomerun_pkt.c hdhomerun/hdhomerun_discover.c ++ SOURCES += hdhomerun/hdhomerun_video.c hdhomerun/hdhomerun_control.c + } + + # Support for PVR-150/250/350/500, etc. on Linux |